import json import sys import time import unittest from concurrent import futures from os import path from gooey.gui import application from gooey.gui.lang.i18n import _ from gooey.gui.util.freeze import getResourcePath from gooey.gui.util.quoting import quote class TestGooeyIntegration(unittest.TestCase): """ A few quick integration tests that exercise Gooey's various run modes WX Python needs to control the main thread. So, in order to simulate a user running through the system, we have to execute the actual assertions in a different thread """ LOCAL_DIR = path.dirname(__file__) def performTest(self, configPath, assertionFunction): """ Primary test harness. Instantiates the WX App, and spawns the threads required to make assertions against it """ with open(configPath, 'r') as f: build_spec = json.loads(f.read()) # swaps the absolute path stored by Gooey at write time # for a relative one based on our current test location target_pyfile = path.split(build_spec['target'].replace('"', ''))[-1] file_path = path.join(path.dirname(__file__), target_pyfile) run_cmd = '{} -u {}'.format(quote(sys.executable), quote(file_path)) build_spec['language_dir'] = getResourcePath('languages') build_spec['target'] = run_cmd app = application.build_app(build_spec=build_spec) executor = futures.ThreadPoolExecutor(max_workers=1) testResult = executor.submit(assertionFunction, app, build_spec) app.MainLoop() testResult.result() # some extra padding time between starting/stopping the wx App app.Destroy() time.sleep(1) def test_gooeyNormalRun(self): """ Tests the happy path through the default run mode of Gooey """ self.performTest(path.join(self.LOCAL_DIR, 'gooey_config__normal.json'), self.gooeySanityTest) def test_gooeySubparserMode(self): """ Tests the happy path through the subparser run mode of Gooey """ self.performTest(path.join(self.LOCAL_DIR, 'gooey_config__subparser.json'), self.gooeySanityTest) def test__gooeyAutoStart(self): """Verifies that issue #201 doesn't regress and auto_start skips the config screen and hops right into the client's program""" self.performTest(path.join(self.LOCAL_DIR, 'gooey_config__autostart.json'), self.verifyAutoStart) def test__gooeyValidation(self): """Verifies that custom validation routines supplied via gooey_options prevents the user from advancing past the configuration page when they fail""" self.performTest(path.join(self.LOCAL_DIR, 'gooey_config__autostart.json'), self.verifyValidators) def verifyValidators(self, app, buildSpec): time.sleep(1) try: app.TopWindow.onStart() # we should still be on the configuration page due to a validation fail title = app.TopWindow.header._header.GetLabel() subtitle = app.TopWindow.header._subheader.GetLabel() self.assertNotEqual(title, buildSpec['program_name']) self.assertNotEqual(subtitle, buildSpec['program_description']) except: app.TopWindow.Destroy() raise else: app.TopWindow.Destroy() return None def verifyAutoStart(self, app, buildSpec): """ When the auto_start flag == True Gooey should skip the configuration screen """ time.sleep(1) try: # Gooey should NOT be showing the name/description headers # present on the config page title = app.TopWindow.header._header.GetLabel() subtitle = app.TopWindow.header._subheader.GetLabel() self.assertNotEqual(title, buildSpec['program_name']) self.assertNotEqual(subtitle, buildSpec['program_description']) # Gooey should be showing the console messages straight away # without manually starting the program title = app.TopWindow.header._header.GetLabel() subtitle = app.TopWindow.header._subheader.GetLabel() self.assertEqual(title,_("running_title")) self.assertEqual(subtitle, _('running_msg')) # Wait for Gooey to swap the header to the final screen while app.TopWindow.header._header.GetLabel() == _("running_title"): time.sleep(.1) # verify that we've landed on the success screen title = app.TopWindow.header._header.GetLabel() subtitle = app.TopWindow.header._subheader.GetLabel() self.assertEqual(title, _("finished_title")) self.assertEqual(subtitle, _('finished_msg')) # and that output was actually written to the console self.assertIn("Success", app.TopWindow.console.textbox.GetValue()) except: app.TopWindow.Destroy() raise else: app.TopWindow.Destroy() return None def gooeySanityTest(self, app, buildSpec): time.sleep(1) try: # Check out header is present and showing data title = app.TopWindow.header._header.GetLabel() subtitle = app.TopWindow.header._subheader.GetLabel() self.assertEqual(title, buildSpec['program_name']) self.assertEqual(subtitle, buildSpec['program_description']) # switch to the run screen app.TopWindow.onStart() # Should find the expected test in the header title = app.TopWindow.header._header.GetLabel() subtitle = app.TopWindow.header._subheader.GetLabel() self.assertEqual(title,_("running_title")) self.assertEqual(subtitle, _('running_msg')) # Wait for Gooey to swap the header to the final screen while app.TopWindow.header._header.GetLabel() == _("running_title"): time.sleep(.1) # verify that we've landed on the success screen title = app.TopWindow.header._header.GetLabel() subtitle = app.TopWindow.header._subheader.GetLabel() self.assertEqual(title, _("finished_title")) self.assertEqual(subtitle, _('finished_msg')) # and that output was actually written to the console self.assertIn("Success", app.TopWindow.console.textbox.GetValue()) except: app.TopWindow.Destroy() raise else: app.TopWindow.Destroy() return None if __name__ == '__main__': unittest.main()