Browse Source

move integration tests

pull/473/head
Chris 6 years ago
parent
commit
a46b475f23
14 changed files with 1242 additions and 174 deletions
  1. 1
      gooey/tests/integration/README.md
  2. 7
      gooey/tests/integration/__init__.py
  3. 68
      gooey/tests/integration/integ_autostart.py
  4. 62
      gooey/tests/integration/integ_subparser_demo.py
  5. 48
      gooey/tests/integration/integ_validations.py
  6. 64
      gooey/tests/integration/integ_widget_demo.py
  7. 0
      gooey/tests/integration/programs/__init__.py
  8. 94
      gooey/tests/integration/programs/all_widgets.py
  9. 147
      gooey/tests/integration/programs/all_widgets_subparser.py
  10. 27
      gooey/tests/integration/programs/auto_start.py
  11. 645
      gooey/tests/integration/programs/gooey_config.json
  12. 33
      gooey/tests/integration/programs/validations.py
  13. 46
      gooey/tests/integration/runner.py
  14. 174
      gooey/tests/test_integration.py

1
gooey/tests/integration/README.md

@ -0,0 +1 @@
These integration tests must be run one at a time. I can't figure out how to clear the wx context between runs and Unittest doesn't allow process isolation..

7
gooey/tests/integration/__init__.py

@ -0,0 +1,7 @@
"""
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
"""

68
gooey/tests/integration/integ_autostart.py

@ -0,0 +1,68 @@
import time
import unittest
from gooey.gui.lang.i18n import _
from tests.integration.programs import auto_start as auto_start_module
class TestGooeyIntegration(unittest.TestCase):
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"""
from gooey.tests.integration import runner
runner.run_integration(auto_start_module, self.verifyAutoStart, auto_start=True)
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:
import wx
wx.CallAfter(app.TopWindow.Destroy)
return None
if __name__ == '__main__':
unittest.main()

62
gooey/tests/integration/integ_subparser_demo.py

@ -0,0 +1,62 @@
import wx
import time
import unittest
from gooey.gui.lang.i18n import _
from tests.integration.programs import \
all_widgets_subparser as all_widgets_subparser_module
class TestGooeyIntegration11(unittest.TestCase):
def test_gooeySubparserMode(self):
""" Tests the happy path through the subparser run mode of Gooey """
from gooey.tests.integration import runner
runner.run_integration(all_widgets_subparser_module, self.gooeySanityTest)
def gooeySanityTest(self, app, buildSpec):
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())
time.sleep(1)
except:
wx.CallAfter(app.TopWindow.Destroy)
raise
else:
wx.CallAfter(app.TopWindow.Destroy)
return None
if __name__ == '__main__':
unittest.main()

48
gooey/tests/integration/integ_validations.py

@ -0,0 +1,48 @@
import time
import unittest
from tests.integration.programs import validations as validations_module
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
"""
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"""
from gooey.tests.integration import runner
runner.run_integration(validations_module, self.verifyValidators)
def verifyValidators(self, app, buildSpec):
time.sleep(1)
try:
app.TopWindow.onStart()
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:
import wx
wx.CallAfter(app.TopWindow.Destroy)
return None
if __name__ == '__main__':
unittest.main()

64
gooey/tests/integration/integ_widget_demo.py

@ -0,0 +1,64 @@
import time
import unittest
import wx
from gooey.gui.lang.i18n import _
from tests.integration.programs import all_widgets as all_widgets_module
class TestGooeyIntegration99(unittest.TestCase):
def test_gooeyNormalRun(self):
""" Tests the happy path through the default run mode of Gooey """
from gooey.tests.integration import runner
runner.run_integration(all_widgets_module, self.gooeySanityTest)
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())
time.sleep(1)
except:
app.TopWindow.Destroy()
raise
else:
wx.CallAfter(app.TopWindow.Destroy)
return None
if __name__ == '__main__':
unittest.main()

0
gooey/tests/integration/programs/__init__.py

94
gooey/tests/integration/programs/all_widgets.py

@ -0,0 +1,94 @@
from gooey import Gooey
from gooey import GooeyParser
@Gooey(
sidebar_title="Your Custom Title",
show_sidebar=True,
dump_build_config=True,
show_success_modal=False,
force_stop_is_error=False,
language='chinese'
)
def main():
dest_vars = [
'textfield',
'textarea',
'password',
'commandfield',
'dropdown',
'listboxie',
'counter',
'overwrite',
'mutextwo',
'filechooser',
'filesaver',
'dirchooser',
'datechooser'
]
parser = get_parser()
args = parser.parse_args()
import time
for i in dest_vars:
assert getattr(args, i) is not None
print("Success")
def get_parser():
desc = "Example application to show Gooey's various widgets"
parser = GooeyParser(description=desc, add_help=False)
parser.add_argument('--textfield', default=2, widget="TextField")
parser.add_argument('--textarea', default="oneline twoline", widget='Textarea')
parser.add_argument('--password', default="hunter42", widget='PasswordField')
parser.add_argument('--commandfield', default="cmdr", widget='CommandField')
parser.add_argument('--dropdown', choices=["one", "two"], default="two", widget='Dropdown')
parser.add_argument('--listboxie',
nargs='+',
default=['Option three', 'Option four'],
choices=['Option one', 'Option two', 'Option three',
'Option four'],
widget='Listbox',
gooey_options={
'height': 300,
'validate': '',
'heading_color': '',
'text_color': '',
'hide_heading': True,
'hide_text': True,
})
parser.add_argument('-c', '--counter', default=3, action='count', widget='Counter')
parser.add_argument("-o", "--overwrite", action="store_true", default=True, widget='CheckBox')
parser.add_argument("-bo", "--blockcheckbox", action="store_true", default=True, widget='BlockCheckbox')
### Mutex Group ###
verbosity = parser.add_mutually_exclusive_group(
required=True,
gooey_options={
'initial_selection': 1
}
)
verbosity.add_argument(
'--mutexone',
default=True,
action='store_true',
help="Show more details")
verbosity.add_argument(
'--mutextwo',
default='mut-2',
widget='TextField')
parser.add_argument("--filechooser", default="fc-value", widget='FileChooser')
parser.add_argument("--filesaver", default="fs-value", widget='FileSaver')
parser.add_argument("--dirchooser", default="dc-value", widget='DirChooser')
parser.add_argument("--datechooser", default="2015-01-01", widget='DateChooser')
parser.add_argument("--multidirchooser", default="2015-01-01", widget='MultiDirChooser')
return parser
if __name__ == '__main__':
main()

147
gooey/tests/integration/programs/all_widgets_subparser.py

@ -0,0 +1,147 @@
"""
Example program to demonstrate Gooey's presentation of subparsers
"""
from gooey import Gooey, GooeyParser
@Gooey(
optional_cols=2,
program_name="Subparser Demo",
dump_build_config=True,
show_success_modal=False)
def main():
dest_vars = [
'textfield',
'textarea',
'password',
'commandfield',
'dropdown',
'listboxie',
'counter',
'overwrite',
'mutextwo',
'filechooser',
'filesaver',
'dirchooser',
'datechooser'
]
parser = get_parser()
args = parser.parse_args()
import time
time.sleep(.6)
for i in dest_vars:
assert getattr(args, i) is not None
print("Success")
def get_parser():
parser = GooeyParser()
subs = parser.add_subparsers(help='commands', dest='command')
parser_one = subs.add_parser('parser1', prog="Parser 1")
parser_one.add_argument('--textfield', default=2, widget="TextField")
parser_one.add_argument('--textarea', default="oneline twoline",
widget='Textarea')
parser_one.add_argument('--password', default="hunter42",
widget='PasswordField')
parser_one.add_argument('--commandfield', default="cmdr",
widget='CommandField')
parser_one.add_argument('--dropdown',
choices=["one", "two"], default="two",
widget='Dropdown')
parser_one.add_argument('--listboxie',
nargs='+',
default=['Option three', 'Option four'],
choices=['Option one', 'Option two', 'Option three',
'Option four'],
widget='Listbox',
gooey_options={
'height': 300,
'validate': '',
'heading_color': '',
'text_color': '',
'hide_heading': True,
'hide_text': True,
}
)
parser_one.add_argument('-c', '--counter', default=3, action='count',
widget='Counter')
#
parser_one.add_argument("-o", "--overwrite", action="store_true",
default=True,
widget='CheckBox')
### Mutex Group ###
verbosity = parser_one.add_mutually_exclusive_group(
required=True,
gooey_options={
'initial_selection': 1
}
)
verbosity.add_argument(
'--mutexone',
default=True,
action='store_true',
help="Show more details")
verbosity.add_argument(
'--mutextwo',
default='mut-2',
widget='TextField')
parser_one.add_argument("--filechooser", default="fc-value", widget='FileChooser')
parser_one.add_argument("--filesaver", default="fs-value", widget='FileSaver')
parser_one.add_argument("--dirchooser", default="dc-value", widget='DirChooser')
parser_one.add_argument("--datechooser", default="2015-01-01", widget='DateChooser')
parser_two = subs.add_parser('parser2', prog="parser 2")
parser_two.add_argument('--textfield', default=2, widget="TextField")
parser_two.add_argument('--textarea', default="oneline twoline", widget='Textarea')
parser_two.add_argument('--password', default="hunter42", widget='PasswordField')
parser_two.add_argument('--commandfield', default="cmdr", widget='CommandField')
parser_two.add_argument('--dropdown', choices=["one", "two"], default="two", widget='Dropdown')
parser_two.add_argument('--listboxie',
nargs='+',
default=['Option three', 'Option four'],
choices=['Option one', 'Option two', 'Option three',
'Option four'],
widget='Listbox',
gooey_options={
'height': 300,
'validate': '',
'heading_color': '',
'text_color': '',
'hide_heading': True,
'hide_text': True,
}
)
parser_two.add_argument('-c', '--counter', default=3, action='count', widget='Counter')
parser_two.add_argument("-o", "--overwrite", action="store_true", default=True, widget='CheckBox')
### Mutex Group ###
verbosity = parser_two.add_mutually_exclusive_group(
required=True,
gooey_options={
'initial_selection': 1
}
)
verbosity.add_argument(
'--mutexone',
default=True,
action='store_true',
help="Show more details")
verbosity.add_argument(
'--mutextwo',
default='mut-2',
widget='TextField')
parser_two.add_argument("--filechooser", default="fc-value", widget='FileChooser')
parser_two.add_argument("--filesaver", default="fs-value", widget='FileSaver')
parser_two.add_argument("--dirchooser", default="dc-value", widget='DirChooser')
parser_two.add_argument("--datechooser", default="2015-01-01", widget='DateChooser')
return parser
if __name__ == '__main__':
main()

27
gooey/tests/integration/programs/auto_start.py

@ -0,0 +1,27 @@
import sys
from gooey import Gooey
from gooey import GooeyParser
from argparse import ArgumentParser
@Gooey(
progress_regex=r"^progress: (-?\d+)%$",
disable_progress_bar_animation=True,
dump_build_config=True,
show_success_modal=False,
auto_start=True
)
def main():
parser = get_parser()
_ = parser.parse_args(sys.argv[1:])
import time
time.sleep(2)
print('Success')
def get_parser():
return GooeyParser(prog="example_progress_bar_1")
if __name__ == '__main__':
main()

645
gooey/tests/integration/programs/gooey_config.json

@ -0,0 +1,645 @@
{
"language": "chinese",
"target": "\"C:\\Users\\Chris\\Dropbox\\pretty_gui\\Gooey\\venv3\\Scripts\\python.exe\" -u \"C:/Users/Chris/Dropbox/pretty_gui/Gooey/gooey/tests/integration/programs/all_widgets.py\"",
"program_name": "all_widgets",
"program_description": "Example application to show Gooey's various widgets",
"sidebar_title": "Your Custom Title",
"default_size": [
610,
530
],
"auto_start": false,
"show_advanced": true,
"run_validators": true,
"encoding": "utf-8",
"show_stop_warning": true,
"show_success_modal": false,
"force_stop_is_error": false,
"poll_external_updates": false,
"return_to_config": false,
"show_restart_button": true,
"requires_shell": true,
"menu": [],
"clear_before_run": false,
"use_legacy_titles": true,
"num_required_cols": 2,
"num_optional_cols": 2,
"manual_start": false,
"monospace_display": false,
"image_dir": "::gooey/default",
"language_dir": "C:\\Users\\Chris\\Dropbox\\pretty_gui\\Gooey\\gooey\\languages",
"progress_regex": null,
"progress_expr": null,
"hide_progress_msg": false,
"disable_progress_bar_animation": false,
"disable_stop_button": false,
"navigation": "SIDEBAR",
"show_sidebar": true,
"tabbed_groups": false,
"group_by_type": true,
"body_bg_color": "#f0f0f0",
"header_bg_color": "#ffffff",
"header_height": 80,
"header_show_title": true,
"header_show_subtitle": true,
"header_image_center": false,
"footer_bg_color": "#f0f0f0",
"sidebar_bg_color": "#f2f2f2",
"terminal_panel_color": "#F0F0F0",
"terminal_font_color": "#000000",
"terminal_font_family": null,
"terminal_font_weight": null,
"terminal_font_size": null,
"richtext_controls": false,
"error_color": "#ea7878",
"layout": "standard",
"widgets": {
"all_widgets.py": {
"command": "::gooey/default",
"name": "all_widgets.py",
"help": null,
"description": "",
"contents": [
{
"name": "Optional Arguments",
"items": [
{
"id": "--textfield",
"type": "TextField",
"cli_type": "optional",
"required": false,
"data": {
"display_name": "textfield",
"help": null,
"required": false,
"nargs": "",
"commands": [
"--textfield"
],
"choices": [],
"default": 2,
"dest": "textfield"
},
"options": {
"error_color": "#ea7878",
"label_color": "#000000",
"help_color": "#363636",
"full_width": false,
"validator": {
"test": "True",
"message": ""
},
"external_validator": {
"cmd": ""
}
}
},
{
"id": "--textarea",
"type": "Textarea",
"cli_type": "optional",
"required": false,
"data": {
"display_name": "textarea",
"help": null,
"required": false,
"nargs": "",
"commands": [
"--textarea"
],
"choices": [],
"default": "oneline twoline",
"dest": "textarea"
},
"options": {
"error_color": "#ea7878",
"label_color": "#000000",
"help_color": "#363636",
"full_width": false,
"validator": {
"test": "True",
"message": ""
},
"external_validator": {
"cmd": ""
}
}
},
{
"id": "--password",
"type": "PasswordField",
"cli_type": "optional",
"required": false,
"data": {
"display_name": "password",
"help": null,
"required": false,
"nargs": "",
"commands": [
"--password"
],
"choices": [],
"default": "hunter42",
"dest": "password"
},
"options": {
"error_color": "#ea7878",
"label_color": "#000000",
"help_color": "#363636",
"full_width": false,
"validator": {
"test": "True",
"message": ""
},
"external_validator": {
"cmd": ""
}
}
},
{
"id": "--commandfield",
"type": "CommandField",
"cli_type": "optional",
"required": false,
"data": {
"display_name": "commandfield",
"help": null,
"required": false,
"nargs": "",
"commands": [
"--commandfield"
],
"choices": [],
"default": "cmdr",
"dest": "commandfield"
},
"options": {
"error_color": "#ea7878",
"label_color": "#000000",
"help_color": "#363636",
"full_width": false,
"validator": {
"test": "True",
"message": ""
},
"external_validator": {
"cmd": ""
}
}
},
{
"id": "--dropdown",
"type": "Dropdown",
"cli_type": "optional",
"required": false,
"data": {
"display_name": "dropdown",
"help": null,
"required": false,
"nargs": "",
"commands": [
"--dropdown"
],
"choices": [
"one",
"two"
],
"default": "two",
"dest": "dropdown"
},
"options": {
"error_color": "#ea7878",
"label_color": "#000000",
"help_color": "#363636",
"full_width": false,
"validator": {
"test": "True",
"message": ""
},
"external_validator": {
"cmd": ""
}
}
},
{
"id": "--listboxie",
"type": "Listbox",
"cli_type": "optional",
"required": false,
"data": {
"display_name": "listboxie",
"help": null,
"required": false,
"nargs": "+",
"commands": [
"--listboxie"
],
"choices": [
"Option one",
"Option two",
"Option three",
"Option four"
],
"default": [
"Option three",
"Option four"
],
"dest": "listboxie"
},
"options": {
"error_color": "#ea7878",
"label_color": "#000000",
"help_color": "#363636",
"full_width": false,
"validator": {
"test": "True",
"message": ""
},
"external_validator": {
"cmd": ""
},
"height": 300,
"validate": "",
"heading_color": "",
"text_color": "",
"hide_heading": true,
"hide_text": true
}
},
{
"id": "-c",
"type": "Counter",
"cli_type": "optional",
"required": false,
"data": {
"display_name": "counter",
"help": null,
"required": false,
"nargs": "",
"commands": [
"-c",
"--counter"
],
"choices": [
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10"
],
"default": "3",
"dest": "counter"
},
"options": {
"error_color": "#ea7878",
"label_color": "#000000",
"help_color": "#363636",
"full_width": false,
"validator": {
"test": "True",
"message": ""
},
"external_validator": {
"cmd": ""
}
}
},
{
"id": "-o",
"type": "CheckBox",
"cli_type": "optional",
"required": false,
"data": {
"display_name": "overwrite",
"help": null,
"required": false,
"nargs": "",
"commands": [
"-o",
"--overwrite"
],
"choices": [],
"default": true,
"dest": "overwrite"
},
"options": {
"error_color": "#ea7878",
"label_color": "#000000",
"help_color": "#363636",
"full_width": false,
"validator": {
"test": "True",
"message": ""
},
"external_validator": {
"cmd": ""
}
}
},
{
"id": "-bo",
"type": "BlockCheckbox",
"cli_type": "optional",
"required": false,
"data": {
"display_name": "blockcheckbox",
"help": null,
"required": false,
"nargs": "",
"commands": [
"-bo",
"--blockcheckbox"
],
"choices": [],
"default": true,
"dest": "blockcheckbox"
},
"options": {
"error_color": "#ea7878",
"label_color": "#000000",
"help_color": "#363636",
"full_width": false,
"validator": {
"test": "True",
"message": ""
},
"external_validator": {
"cmd": ""
}
}
},
{
"id": "94c2fd11-1925-4cc8-8634-44ef0ce07986",
"type": "RadioGroup",
"cli_type": "optional",
"group_name": "Choose Option",
"required": true,
"options": {
"error_color": "#ea7878",
"label_color": "#000000",
"help_color": "#363636",
"full_width": false,
"validator": {
"type": "local",
"test": "lambda x: True",
"message": ""
},
"external_validator": {
"cmd": ""
},
"initial_selection": 1
},
"data": {
"commands": [
[
"--mutexone"
],
[
"--mutextwo"
]
],
"widgets": [
{
"id": "--mutexone",
"type": "CheckBox",
"cli_type": "optional",
"required": false,
"data": {
"display_name": "mutexone",
"help": "Show more details",
"required": false,
"nargs": "",
"commands": [
"--mutexone"
],
"choices": [],
"default": true,
"dest": "mutexone"
},
"options": {
"error_color": "#ea7878",
"label_color": "#000000",
"help_color": "#363636",
"full_width": false,
"validator": {
"test": "True",
"message": ""
},
"external_validator": {
"cmd": ""
}
}
},
{
"id": "--mutextwo",
"type": "TextField",
"cli_type": "optional",
"required": false,
"data": {
"display_name": "mutextwo",
"help": null,
"required": false,
"nargs": "",
"commands": [
"--mutextwo"
],
"choices": [],
"default": "mut-2",
"dest": "mutextwo"
},
"options": {
"error_color": "#ea7878",
"label_color": "#000000",
"help_color": "#363636",
"full_width": false,
"validator": {
"test": "True",
"message": ""
},
"external_validator": {
"cmd": ""
}
}
}
]
}
},
{
"id": "--filechooser",
"type": "FileChooser",
"cli_type": "optional",
"required": false,
"data": {
"display_name": "filechooser",
"help": null,
"required": false,
"nargs": "",
"commands": [
"--filechooser"
],
"choices": [],
"default": "fc-value",
"dest": "filechooser"
},
"options": {
"error_color": "#ea7878",
"label_color": "#000000",
"help_color": "#363636",
"full_width": false,
"validator": {
"test": "True",
"message": ""
},
"external_validator": {
"cmd": ""
}
}
},
{
"id": "--filesaver",
"type": "FileSaver",
"cli_type": "optional",
"required": false,
"data": {
"display_name": "filesaver",
"help": null,
"required": false,
"nargs": "",
"commands": [
"--filesaver"
],
"choices": [],
"default": "fs-value",
"dest": "filesaver"
},
"options": {
"error_color": "#ea7878",
"label_color": "#000000",
"help_color": "#363636",
"full_width": false,
"validator": {
"test": "True",
"message": ""
},
"external_validator": {
"cmd": ""
}
}
},
{
"id": "--dirchooser",
"type": "DirChooser",
"cli_type": "optional",
"required": false,
"data": {
"display_name": "dirchooser",
"help": null,
"required": false,
"nargs": "",
"commands": [
"--dirchooser"
],
"choices": [],
"default": "dc-value",
"dest": "dirchooser"
},
"options": {
"error_color": "#ea7878",
"label_color": "#000000",
"help_color": "#363636",
"full_width": false,
"validator": {
"test": "True",
"message": ""
},
"external_validator": {
"cmd": ""
}
}
},
{
"id": "--datechooser",
"type": "DateChooser",
"cli_type": "optional",
"required": false,
"data": {
"display_name": "datechooser",
"help": null,
"required": false,
"nargs": "",
"commands": [
"--datechooser"
],
"choices": [],
"default": "2015-01-01",
"dest": "datechooser"
},
"options": {
"error_color": "#ea7878",
"label_color": "#000000",
"help_color": "#363636",
"full_width": false,
"validator": {
"test": "True",
"message": ""
},
"external_validator": {
"cmd": ""
}
}
},
{
"id": "--multidirchooser",
"type": "MultiDirChooser",
"cli_type": "optional",
"required": false,
"data": {
"display_name": "multidirchooser",
"help": null,
"required": false,
"nargs": "",
"commands": [
"--multidirchooser"
],
"choices": [],
"default": "2015-01-01",
"dest": "multidirchooser"
},
"options": {
"error_color": "#ea7878",
"label_color": "#000000",
"help_color": "#363636",
"full_width": false,
"validator": {
"test": "True",
"message": ""
},
"external_validator": {
"cmd": ""
}
}
}
],
"groups": [],
"description": null,
"options": {
"label_color": "#000000",
"description_color": "#363636",
"legacy": {
"required_cols": 2,
"optional_cols": 2
},
"columns": 2,
"padding": 10,
"show_border": false
}
}
]
}
}
}

33
gooey/tests/integration/programs/validations.py

@ -0,0 +1,33 @@
import time
from gooey import Gooey
from gooey import GooeyParser
@Gooey(
sidebar_title="Your Custom Title",
show_sidebar=True,
show_success_modal=False,
force_stop_is_error=False,
)
def main():
parser = get_parser()
args = parser.parse_args()
time.sleep(2)
print("Success")
def get_parser():
"""
A simple parser with a single required argument and no default thus
ensuring that clicking the start button in the UI will throw
a validation error.
"""
desc = "Example application to show Gooey's various widgets"
parser = GooeyParser(description=desc, add_help=False)
parser.add_argument('--textfield', widget="TextField", required=True)
return parser
if __name__ == '__main__':
main()

46
gooey/tests/integration/runner.py

@ -0,0 +1,46 @@
import os
import time
from concurrent import futures
from gooey.gui.util.freeze import getResourcePath
from gooey.python_bindings import config_generator
from gooey.util.functional import merge
def run_integration(module, assertionFunction, **kwargs):
"""
Integration test harness.
WXPython is *super* finicky when it comes to integration tests. It needs
the main Python thread for its app loop, which means we have to integration
test on a separate thread. The causes further strangeness in how Unittest
and WXPython interact. In short, each test must be in its own module and
thus import its own wx instance, and be run in its own "space."
So long as the above is satisfied, then integration tests can run reliably.
"""
from gooey.gui import application
options = merge({
'image_dir': '::gooey/default',
'language_dir': getResourcePath('languages'),
'show_success_modal': False
}, kwargs)
module_path = os.path.abspath(module.__file__)
parser = module.get_parser()
build_spec = config_generator.create_from_parser(parser, module_path, **options)
time.sleep(2)
app = application.build_app(build_spec=build_spec)
executor = futures.ThreadPoolExecutor(max_workers=1)
# executor runs in parallel and will submit a wx.Destroy request
# when done making its assertions
testResult = executor.submit(assertionFunction, app, build_spec)
# main loop blocks the main thread
app.MainLoop()
# .result() blocks as well while we wait for the thread to finish
# any waiting it may be doing.
testResult.result()
del app

174
gooey/tests/test_integration.py

@ -1,174 +0,0 @@
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()
Loading…
Cancel
Save