class Engine(BaseEngine): given_definition = GivenDefinition(setup=GivenProperty(Str()), state=GivenProperty(Str())) def __init__(self, paths, rewrite=False): self.path = paths self._rewrite = rewrite def set_up(self): virtualenv = (hitchbuildpy.VirtualenvBuild( self.path.gen / "venv", hitchbuildpy.PyenvBuild(self.path.share / "python3.7.0", "3.7.0"), ).with_requirementstxt("requirements.txt")) virtualenv.ensure_built() self.example_py_code = (ExamplePythonCode( virtualenv.bin.python, self.path.gen).with_setup_code( self.given.get("setup", "")).with_terminal_size( 160, 100).with_strings(state=self.given["state"]).with_modules( "game.py", "state.py")) @no_stacktrace_for(HitchRunPyException) def run(self, code, will_output=None): result = self.example_py_code.with_code(code).run() if will_output is not None: try: Templex(will_output).assert_match(result.output) except AssertionError: if self._rewrite: self.current_step.update(**{"will output": result.output}) else: raise
class Engine(BaseEngine): given_definition = GivenDefinition(website=GivenProperty(Str())) def __init__(self, paths): self.path = paths def set_up(self): print("set up") print(self.given["website"]) def form_filled(self, **textboxes): for name, contents in sorted(textboxes.items()): print("{}: {}".format(name, contents)) def clicked(self, name): print(name) def email_was_sent(self): print("email was sent") def on_failure(self, result): print("failure") def on_success(self): print("success") def tear_down(self): print("tear down run")
class Engine(BaseEngine): given_definition = GivenDefinition(string=GivenProperty(Str())) #info_definition = InfoDefinition(jiras=InfoProperty(schema=CommaSeparated(Str()))) def __init__(self, parser, rewrite=False): self._parser = parser self._rewrite = rewrite def set_up(self): pass @no_stacktrace_for(CommandError) @no_stacktrace_for(AssertionError) def lexed_as(self, example_json): try: Templex(example_json).assert_match( self._parser.lex_to_json(self.given['string'])) except AssertionError: if self._rewrite: self.current_step.update(example_json=self._parser.lex_to_json( self.given['string'])) else: raise @no_stacktrace_for(CommandError) @no_stacktrace_for(AssertionError) def parsed_as(self, example_json): try: Templex(example_json).assert_match( self._parser.parse_to_json(self.given['string'])) except AssertionError: if self._rewrite: self.current_step.update(example_json=self._parser. parse_to_json(self.given['string'])) else: raise def tear_down(self): if self._rewrite: self.new_story.save()
class Engine(BaseEngine): given_definition = GivenDefinition(exercise=GivenProperty(Str()), ) def __init__(self, paths, rewrite): self._path = paths self._rewrite = rewrite def set_up(self): self._db_service = build.pgdata(self._path).server() self._db_service.start() self._psql = self._db_service.psql( "-U", "myuser", "-p", "15432", "-d", "mydb", ).with_env(PG_PASSWORD="******") @no_stacktrace_for(AssertionError) def sql(self, expected_result): exercise_file = self._path.project / self.given['exercise'] assert exercise_file.exists(), "{} doesn't exist.".format( self.given['exercise']) actual_result = self._psql("-f", self._path.project / self.given['exercise']).output() if actual_result != expected_result: try: Templex(expected_result).assert_match(actual_result) except AssertionError: if self._rewrite: self.current_step.update(expected_result=actual_result) else: raise def tear_down(self): if hasattr(self, '_db_service'): self._db_service.stop()
class Engine(BaseEngine): """Python engine for running tests.""" given_definition = GivenDefinition( scripts=GivenProperty(MapPattern(Str(), Str())), python_version=GivenProperty(Str()), pexpect_version=GivenProperty(Str()), icommandlib_version=GivenProperty(Str()), setup=GivenProperty(Str()), files=GivenProperty(MapPattern(Str(), Str())), code=GivenProperty(Str()), ) info_definition = InfoDefinition( importance=InfoProperty(schema=Int()), docs=InfoProperty(schema=Str()), fails_on_python_2=InfoProperty(schema=Bool()), ) def __init__(self, keypath, rewrite=False): self.path = keypath self._rewrite = rewrite self._cprofile = False def set_up(self): """Set up your applications and the test environment.""" self.path.state = self.path.gen.joinpath("state") if self.path.state.exists(): self.path.state.rmtree(ignore_errors=True) self.path.state.mkdir() for script in self.given.get("scripts", []): script_path = self.path.state.joinpath(script) if not script_path.dirname().exists(): script_path.dirname().makedirs() script_path.write_text(self.given["scripts"][script]) script_path.chmod("u+x") for filename, contents in self.given.get("files", {}).items(): self.path.state.joinpath(filename).write_text(contents) self.python = hitchpylibrarytoolkit.project_build( "commandlib", self.path, self.given["python version"] ).bin.python self.example_py_code = ( ExamplePythonCode(self.python, self.path.state) .with_code(self.given.get("code", "")) .with_setup_code(self.given.get("setup", "")) ) def _story_friendly_output(self, text): return text.replace(self.path.state, "/path/to") @no_stacktrace_for(AssertionError) @no_stacktrace_for(HitchRunPyException) @validate( code=Str(), will_output=Str(), raises=Map( { Optional("type"): Map({"in python 2": Str(), "in python 3": Str()}) | Str(), Optional("message"): Map({"in python 2": Str(), "in python 3": Str()}) | Str(), } ), ) def run(self, code, will_output=None, raises=None): to_run = self.example_py_code.with_code(code) if self._cprofile: to_run = to_run.with_cprofile( self.path.profile.joinpath("{0}.dat".format(self.story.slug)) ) result = ( to_run.expect_exceptions().run() if raises is not None else to_run.run() ) if will_output is not None: actual_output = "\n".join( [line.rstrip() for line in result.output.split("\n")] ) try: Templex(will_output).assert_match(actual_output) except AssertionError: if self._rewrite: self.current_step.update(**{"will output": actual_output}) else: raise if raises is not None: differential = False # Difference between python 2 and python 3 output? exception_type = raises.get("type") message = raises.get("message") if exception_type is not None: if not isinstance(exception_type, str): differential = True exception_type = ( exception_type["in python 2"] if self.given["python version"].startswith("2") else exception_type["in python 3"] ) if message is not None: if not isinstance(message, str): differential = True message = ( message["in python 2"] if self.given["python version"].startswith("2") else message["in python 3"] ) try: result = self.example_py_code.expect_exceptions().run() result.exception_was_raised(exception_type) exception_message = self._story_friendly_output( result.exception.message ) Templex(exception_message).assert_match(message) except AssertionError: if self._rewrite and not differential: new_raises = raises.copy() new_raises["message"] = self._story_friendly_output( result.exception.message ) self.current_step.update(raises=new_raises) else: raise def file_contents_will_be(self, filename, contents): file_contents = "\n".join( [ line.rstrip() for line in self.path.state.joinpath(filename) .bytes() .decode("utf8") .strip() .split("\n") ] ) try: # Templex(file_contents).assert_match(contents.strip()) assert file_contents == contents.strip(), "{0} not {1}".format( file_contents, contents.strip() ) except AssertionError: if self._rewrite: self.current_step.update(contents=file_contents) else: raise def pause(self, message="Pause"): import IPython IPython.embed() def on_success(self): if self._cprofile: self.python( self.path.key.joinpath("printstats.py"), self.path.profile.joinpath("{0}.dat".format(self.story.slug)), ).run()
class Engine(BaseEngine): """Python engine for running tests.""" given_definition = GivenDefinition( python_version=GivenProperty(Str()), selenium_version=GivenProperty(Str()), website=GivenProperty(MapPattern(Str(), Str())), selectors_yml=GivenProperty(Str()), javascript=GivenProperty(Str()), setup=GivenProperty(Str()), code=GivenProperty(Str()), ) info_definition = InfoDefinition( status=InfoProperty(schema=Enum(["experimental", "stable"])), docs=InfoProperty(schema=Str()), ) def __init__(self, keypath, settings): self.path = keypath self.settings = settings def set_up(self): """Set up your applications and the test environment.""" self.path.state = self.path.gen.joinpath("state") if self.path.state.exists(): self.path.state.rmtree(ignore_errors=True) self.path.state.mkdir() self.path.profile = self.path.gen.joinpath("profile") dirtemplate.DirTemplate( "webapp", self.path.key / "htmltemplate", self.path.state ).with_vars(javascript=self.given.get("javascript", "")).with_files( base_html={ filename: { "content": content } for filename, content in self.given.get("website", {}).items() }).ensure_built() self.path.state.joinpath("selectors.yml").write_text( self.given["selectors.yml"]) self.server = (python("-m", "http.server").in_dir(self.path.state / "webapp").pexpect()) self.server.expect("Serving HTTP on 0.0.0.0") if not self.path.profile.exists(): self.path.profile.mkdir() self.python = project_build(self.path, self.given["python version"], self.given["selenium version"]).bin.python self.example_py_code = (ExamplePythonCode( self.python, self.path.state).with_setup_code(self.given.get( "setup", "")).with_terminal_size(160, 100).with_long_strings()) @validate( code=Str(), will_output=Map({ "in python 2": Str(), "in python 3": Str() }) | Str(), raises=Map({ Optional("type"): Map({ "in python 2": Str(), "in python 3": Str() }) | Str(), Optional("message"): Map({ "in python 2": Str(), "in python 3": Str() }) | Str(), }), in_interpreter=Bool(), ) def run(self, code, will_output=None, raises=None, in_interpreter=False): if in_interpreter: code = "{0}\nprint(repr({1}))".format( "\n".join(code.strip().split("\n")[:-1]), code.strip().split("\n")[-1]) to_run = self.example_py_code.with_code(code) if self.settings.get("cprofile"): to_run = to_run.with_cprofile( self.path.profile.joinpath("{0}.dat".format(self.story.slug))) result = (to_run.expect_exceptions().run() if raises is not None else to_run.run()) if will_output is not None: actual_output = "\n".join( [line.rstrip() for line in result.output.split("\n")]) try: Templex(will_output).assert_match(actual_output) except AssertionError: if self.settings.get("rewrite"): self.current_step.update(**{"will output": actual_output}) else: raise if raises is not None: differential = False # Difference between python 2 and python 3 output? exception_type = raises.get("type") message = raises.get("message") if exception_type is not None: if not isinstance(exception_type, str): differential = True exception_type = ( exception_type["in python 2"] if self.given["python version"].startswith("2") else exception_type["in python 3"]) if message is not None: if not isinstance(message, str): differential = True message = (message["in python 2"] if self.given["python version"].startswith("2") else message["in python 3"]) try: result.exception_was_raised(exception_type, message) except ExpectedExceptionMessageWasDifferent: if self.settings.get("rewrite") and not differential: new_raises = raises.copy() new_raises["message"] = result.exception.message self.current_step.update(raises=new_raises) else: raise def do_nothing(self): pass def pause(self, message="Pause"): import IPython IPython.embed() def tear_down(self): self.server.kill(signal.SIGTERM) self.server.wait()
class Engine(BaseEngine): """Python engine for running tests.""" given_definition = GivenDefinition( yaml_snippet=GivenProperty( Str(), document="yaml_snippet:\n```yaml\n{{ yaml_snippet }}\n```"), yaml_snippet_1=GivenProperty( Str(), document="yaml_snippet_1:\n```yaml\n{{ yaml_snippet_1 }}\n```"), yaml_snippet_2=GivenProperty( Str(), document="yaml_snippet_2:\n```yaml\n{{ yaml_snippet_2 }}\n```"), modified_yaml_snippet=GivenProperty( Str(), document= "modified_yaml_snippet:\n```yaml\n{{ modified_yaml_snippet }}\n```" ), python_version=GivenProperty(Str()), ruamel_version=GivenProperty(Str()), setup=GivenProperty(Str(), document="```python\n{{ setup }}\n```"), ) info_definition = InfoDefinition( status=InfoProperty(schema=Enum(["experimental", "stable"])), docs=InfoProperty(schema=Str()), fails_on_python_2=InfoProperty(schema=Bool()), description=InfoProperty(schema=Str()), experimental=InfoProperty(schema=Bool()), ) def __init__(self, keypath, python_path=None, rewrite=False, cprofile=False): self.path = keypath self._python_path = python_path self._rewrite = rewrite self._cprofile = cprofile def set_up(self): """Set up your applications and the test environment.""" self.path.profile = self.path.gen.joinpath("profile") if not self.path.profile.exists(): self.path.profile.mkdir() if not self._python_path: self.python = hitchpylibrarytoolkit.project_build( "strictyaml", self.path, self.given["python version"], { "ruamel.yaml": self.given["ruamel version"] }, ).bin.python else: self.python = Path(self._python_path) assert self.python.exists() self.example_py_code = (ExamplePythonCode( self.python, self.path.gen).with_code(self.given.get( "code", "")).with_setup_code(self.given.get( "setup", "")).with_terminal_size(160, 100).with_strings( yaml_snippet_1=self.given.get("yaml_snippet_1"), yaml_snippet=self.given.get("yaml_snippet"), yaml_snippet_2=self.given.get("yaml_snippet_2"), modified_yaml_snippet=self.given.get( "modified_yaml_snippet"), )) @no_stacktrace_for(AssertionError) @no_stacktrace_for(HitchRunPyException) @validate( code=Str(), will_output=Map({ "in python 2": Str(), "in python 3": Str() }) | Str(), raises=Map({ Optional("type"): CODE_TYPE, Optional("message"): CODE_TYPE }), in_interpreter=Bool(), ) def run( self, code, will_output=None, yaml_output=True, raises=None, in_interpreter=False, ): if in_interpreter: code = "{0}\nprint(repr({1}))".format( "\n".join(code.strip().split("\n")[:-1]), code.strip().split("\n")[-1]) to_run = self.example_py_code.with_code(code) if self._cprofile: to_run = to_run.with_cprofile( self.path.profile.joinpath("{0}.dat".format(self.story.slug))) if raises is None: result = (to_run.expect_exceptions().run() if raises is not None else to_run.run()) if will_output is not None: actual_output = "\n".join( [line.rstrip() for line in result.output.split("\n")]) try: Templex(will_output).assert_match(actual_output) except AssertionError: if self._rewrite: self.current_step.update( **{"will output": actual_output}) else: raise elif raises is not None: differential = False # Difference between python 2 and python 3 output? exception_type = raises.get("type") message = raises.get("message") if exception_type is not None: if not isinstance(exception_type, str): differential = True exception_type = ( exception_type["in python 2"] if self.given["python version"].startswith("2") else exception_type["in python 3"]) if message is not None: if not isinstance(message, str): differential = True message = (message["in python 2"] if self.given["python version"].startswith("2") else message["in python 3"]) try: result = to_run.expect_exceptions().run() result.exception_was_raised(exception_type, message) except ExpectedExceptionMessageWasDifferent as error: if self._rewrite and not differential: new_raises = raises.copy() new_raises["message"] = result.exception.message self.current_step.update(raises=new_raises) else: raise def pause(self, message="Pause"): import IPython IPython.embed() def on_success(self): if self._rewrite: self.new_story.save() if self._cprofile: self.python( self.path.key.joinpath("printstats.py"), self.path.profile.joinpath("{0}.dat".format(self.story.slug)), ).run()
class Engine(BaseEngine): """Python engine for running tests.""" given_definition = GivenDefinition( files=GivenProperty(MapPattern(Str(), Str())), python_version=GivenProperty(Str()), setup=GivenProperty(Str()), ) info_definition = InfoDefinition( docs=InfoProperty(schema=Str()), ) def __init__(self, paths, settings): self.path = paths self.settings = settings self._build = hitchpylibrarytoolkit.PyLibraryBuild( "hitchqs", self.path, ) def set_up(self): """Set up the environment ready to run the stories.""" self._build.ensure_built() self.path.state = self.path.gen.joinpath("state") if self.path.state.exists(): self.path.state.rmtree() self.path.state.mkdir() for filename, content in self.given['files'].items(): filepath = self.path.state.joinpath(filename) if not filepath.dirname().exists(): filepath.dirname().makedirs() filepath.write_text(content) self.python = self._build.bin.python def _process_exception(self, string): return string.replace(self.path.state, "/path/to") @no_stacktrace_for(AssertionError) @no_stacktrace_for(HitchRunPyException) @validate( code=Str(), will_output=Str(), raises=Map({ Optional("type"): Str(), Optional("message"): Str(), }) ) def run(self, code, will_output=None, raises=None): self.example_py_code = ExamplePythonCode(self.python, self.path.state)\ .with_terminal_size(160, 100)\ .with_setup_code(self.given['setup'])\ .in_dir(self.path.state) to_run = self.example_py_code.with_code(code) if self.settings.get("cprofile"): to_run = to_run.with_cprofile( self.path.profile.joinpath("{0}.dat".format(self.story.slug)) ) result = to_run.expect_exceptions().run() if raises is not None else to_run.run() actual_output = result.output if will_output is not None: try: Templex(will_output).assert_match(actual_output) except AssertionError: if self.settings.get("overwrite artefacts"): self.current_step.update(**{"will output": actual_output}) else: raise if raises is not None: exception_type = raises.get('type') message = raises.get('message') try: result.exception_was_raised(exception_type) exception_message = self._process_exception(result.exception.message) Templex(message).assert_match(exception_message) except AssertionError: if self.settings.get("overwrite artefacts"): new_raises = raises.copy() new_raises['message'] = exception_message self.current_step.update(raises=new_raises) else: raise @no_stacktrace_for(AssertionError) @validate(files=MapPattern(Str(), Str())) def build_output_is(self, files): for filename, content in files.items(): filepath = self.path.state.joinpath(filename) assert filepath.exists(), "{0} does not exist".format(filename) if content != "": try: Templex(content).assert_match(filepath.text()) except AssertionError as error: raise AssertionError("{0} is nonmatching:\n\n{1}".format(filename, error)) actual_files = [ path.replace(self.path.state + "/", "") for path in pathquery(self.path.state.joinpath("example")).is_not_dir() ] assert len(actual_files) == len(files.keys()), \ "Should be:\n\n{0}\n\nAre actually:\n\n{1}\n".format( '\n'.join(files.keys()), '\n'.join(actual_files), ) def on_success(self): self.new_story.save()
class Engine(BaseEngine): """Python engine for running tests.""" given_definition = GivenDefinition( setup=GivenProperty(Str()), boxname=GivenProperty(Str()), vmname=GivenProperty(Str()), issue=GivenProperty(Str()), files=GivenProperty(MapPattern(Str(), Str())), python_version=GivenProperty(Str()), ) info_definition = InfoDefinition( status=InfoProperty(schema=Enum(["experimental", "stable"])), docs=InfoProperty(schema=Str()), ) def __init__(self, paths, settings): self.path = paths self.settings = settings def set_up(self): """Set up your applications and the test environment.""" self.path.cachestate = self.path.gen.joinpath("cachestate") self.path.state = self.path.gen.joinpath("state") self.path.working_dir = self.path.gen.joinpath("working") self.path.build_path = self.path.gen.joinpath("build_path") self.path.localsync = self.path.gen.joinpath("local_sync") if self.path.state.exists(): self.path.state.rmtree(ignore_errors=True) self.path.state.mkdir() if self.path.localsync.exists(): self.path.localsync.rmtree(ignore_errors=True) self.path.localsync.mkdir() if self.path.build_path.exists(): self.path.build_path.rmtree(ignore_errors=True) self.path.build_path.mkdir() self.python = hitchpylibrarytoolkit.project_build( "hitchbuildvagrant", self.path, self.given.get("python_version", "3.7.0")).bin.python if not self.path.cachestate.exists(): self.path.cachestate.mkdir() for filename, contents in self.given.get("files", {}).items(): filepath = self.path.state.joinpath(filename) if not filepath.dirname().exists(): filepath.dirname().makedirs() filepath.write_text(contents) if self.path.working_dir.exists(): self.path.working_dir.rmtree(ignore_errors=True) self.path.working_dir.mkdir() self.example_py_code = (ExamplePythonCode( self.python, self.path.state).with_setup_code( self.given.get("setup", "").replace( "/path/to/share", self.path.cachestate)).with_terminal_size( 160, 100).with_long_strings( share=str(self.path.cachestate), build_path=str(self.path.build_path), issue=str(self.given.get("issue")), boxname=str(self.given.get("boxname")), vmname=str(self.given.get("vmname")), local_sync_path=str(self.path.localsync), )) @no_stacktrace_for(HitchRunPyException) def run(self, code): self.example_py_code.with_code(code).run() def write_to_localsync(self, **files): for filename, contents in files.items(): self.path.localsync.joinpath(filename).write_text(contents) def delete_localsync_file(self, filename): self.path.localsync.joinpath(filename).remove() def write_file(self, filename, contents): self.path.state.joinpath(filename).write_text(contents) def raises_exception(self, message=None, exception_type=None): try: result = self.example_python_code.expect_exceptions().run( self.path.state, self.python) result.exception_was_raised(exception_type, message.strip()) except ExpectedExceptionMessageWasDifferent as error: if self.settings.get("rewrite"): self.current_step.update(message=error.actual_message) else: raise def file_contains(self, filename, contents): assert (self.path.working_dir.joinpath(filename).bytes().decode("utf8") == contents) @validate(duration=Float()) def sleep(self, duration): import time time.sleep(duration) def pause(self, message="Pause"): import IPython IPython.embed() def on_failure(self, reason): pass def tear_down(self): for vagrantfile in pathquery(self.path.state).named("Vagrantfile"): Command("vagrant", "destroy", "-f").in_dir(vagrantfile.abspath().dirname()).run()
class Engine(BaseEngine): """Python engine for running tests.""" given_definition = GivenDefinition( python_version=GivenProperty(Str()), files=GivenProperty(MapPattern(Str(), Str())), ) info_definition = InfoDefinition( status=InfoProperty(schema=Enum(["experimental", "stable"])), docs=InfoProperty(schema=Str()), fails_on_python_2=InfoProperty(schema=Bool()), description=InfoProperty(schema=Str()), experimental=InfoProperty(schema=Bool()), ) def __init__(self, keypath, rewrite=False, build=False): self.path = keypath self._rewrite = rewrite self._build = hitchpylibrarytoolkit.PyLibraryBuild( "hitchqs", self.path, ) def set_up(self): """Set up your applications and the test environment.""" self._build.ensure_built() self.path.state = self.path.project.parent / "tempqs" if self.path.state.exists(): self.path.state.rmtree(ignore_errors=True) self.path.state.mkdir() for filename, contents in self.given.get("files", {}).items(): filepath = self.path.state.joinpath(filename) if not filepath.dirname().exists(): filepath.dirname().makedirs() filepath.write_text(contents) self.path.profile = self.path.gen.joinpath("profile") if not self.path.profile.exists(): self.path.profile.mkdir() self.qs = self._build.bin.quickstart def _run(self, command, args, will_output=None, exit_code=0, timeout=5): process = command(*shlex.split(args)).interact().screensize(160, 80).run() process.wait_for_finish() actual_output = process.stripshot()\ .replace(self.path.state, "/path/to") # Replace 35.1 SECONDS with n.n SECONDS actual_output = re.sub("[0-9]+\.[0-9]", "n.n", actual_output) if will_output is not None: try: Templex(will_output).assert_match(actual_output) except AssertionError: if self._rewrite: self.current_step.update(**{"will output": actual_output}) else: raise assert process.exit_code == exit_code, "Exit code should be {} was {}, output:\n{}".format( exit_code, process.exit_code, actual_output, ) @validate(timeout=Int(), exit_code=Int()) @no_stacktrace_for(AssertionError) def quickstart(self, args, will_output=None, exit_code=0, timeout=5): self._run(self.qs.in_dir(self.path.state), args, will_output, exit_code, timeout=timeout) @no_stacktrace_for(AssertionError) def hk(self, args, will_output=None, exit_code=0, timeout=5, in_dir=""): if self._build: self._run(Command("hk").in_dir(self.path.state / in_dir), args, will_output, exit_code, timeout=timeout) def initial_hk(self, args="", in_dir=""): if self._build: Command("hk", *shlex.split(args)).in_dir(self.path.state / in_dir).run() @validate(filenames=Seq(Str())) def files_appear(self, filenames): appeared = set() should_appear = set(filenames) for existing_file in pathquery(self.path.state): if "__pycache__" not in existing_file and not existing_file.isdir(): appeared.add(str(existing_file.relpath(self.path.state))) diff = should_appear.symmetric_difference(appeared) assert diff == set(), \ "Difference in files that appeared:\n{}".format('\n'.join(diff)) def pause(self, message="Pause"): import IPython IPython.embed() def tear_down(self): if self._build: if self.path.state.exists(): Command("hk", "--clean").ignore_errors().in_dir(self.path.state).run()
class Engine(BaseEngine): """Engine for running tests and inspecting result.""" given_definition = GivenDefinition( files=GivenProperty(MapPattern(Str(), Str())), setup=GivenProperty(Str()), ) def __init__(self, paths, rewrite, debug): self.path = paths self._rewrite = rewrite self._debug = debug def set_up(self): self.path.state = self.path.gen.joinpath("state") self.path.state.rmtree(ignore_errors=True) self.path.state.mkdir() self.path.example = self.path.project / "example" if self.path.example.exists(): self.path.example.rmtree() self.path.example.makedirs() for filename, text in self.given.get("files", {}).items(): filepath = self.path.example.joinpath(filename) if not filepath.dirname().exists(): filepath.dirname().makedirs() filepath.write_text(text) ubuntu = hitchbuildvagrant.Box("hitchkey", "ubuntu-trusty-64")\ .with_download_path(self.path.share)\ .which_syncs(self.path.project, "/hitchkey") setup_code = self.given.get("setup", "") class PythonSnapshot(hitchbuildvagrant.Snapshot): def setup(self): self.cmd(setup_code).run() self.cmd("sudo apt-get install python-setuptools -y").run() self.cmd("sudo apt-get install build-essential -y").run() self.cmd("sudo apt-get install python-pip -y").run() self.cmd("sudo apt-get install python-virtualenv -y").run() self.cmd("sudo apt-get install python3 -y").run() self.cmd("cd /hitchkey/ ; sudo pip install .").run() setuphash = md5(setup_code.encode('utf8')).hexdigest() self.snapshot = PythonSnapshot("hitchkey_{}".format(setuphash), ubuntu).with_build_path(self.path.gen) self.snapshot.ensure_built() self.snapshot.box.vagrant("rsync").run() self.snapshot.cmd( "cd /hitchkey/ ; sudo pip uninstall hitchkey -y ; sudo pip install ." ).run() @validate(timeout=Int(), exit_code=Int()) @no_stacktrace_for(ICommandError) @no_stacktrace_for(AssertionError) def run(self, cmd=None, will_output=None, timeout=240, exit_code=0): process = self.snapshot.cmd(cmd.replace("\n", " ; ")).interact().screensize( 160, 100).run() process.wait_for_finish(timeout=timeout) actual_output = '\n'.join(process.stripshot().split("\n")[:-1]) if will_output is not None: try: Templex(will_output).assert_match(actual_output) except AssertionError: if self._rewrite: self.current_step.update(**{"will output": actual_output}) else: raise assert process.exit_code == exit_code, "Exit code should be {} was {}, output:\n{}".format( exit_code, process.exit_code, actual_output, ) def pause(self): import IPython IPython.embed() def on_failure(self, reason): if self._debug: import IPython IPython.embed() def tear_down(self): """Clean out the state directory.""" if hasattr(self, 'snapshot'): self.snapshot.shutdown()
class Engine(BaseEngine): given_definition = GivenDefinition( python_version=GivenProperty(Str()), setup=GivenProperty(Str()), files=GivenProperty(MapPattern(Str(), Str())), ) def __init__(self, build, rewrite=False, cprofile=False): self._build = build self._rewrite = rewrite self._cprofile = cprofile def set_up(self): self._build.ensure_built() for filename, contents in self.given.get("files", {}).items(): filepath = self._build.working.parent.joinpath(filename) if not filepath.dirname().exists(): filepath.dirname().makedirs() filepath.write_text(contents) def assert_text(self, will_output, actual_output): Templex(will_output).assert_match(actual_output) def _story_friendly_output(self, text): return text @no_stacktrace_for(AssertionError) @no_stacktrace_for(HitchRunPyException) @validate( code=Str(), will_output=Str(), environment_vars=MapPattern(Str(), Str()), raises=Map({ Optional("type"): Str(), Optional("message"): Str() }), ) def run(self, code, will_output=None, environment_vars=None, raises=None): self.example_py_code = ( self._build.example_python_code.with_terminal_size( 160, 100).with_env( **{} if environment_vars is None else environment_vars). with_setup_code(self.given.get("setup", ""))) to_run = self.example_py_code.with_code(code) if self._cprofile: to_run = to_run.with_cprofile( self.path.profile.joinpath("{0}.dat".format(self.story.slug))) result = (to_run.expect_exceptions().run() if raises is not None else to_run.run()) actual_output = self._story_friendly_output(result.output) if will_output is not None: try: self.assert_text(will_output, actual_output) except AssertionError: if self._rewrite: self.current_step.update(**{"will output": actual_output}) else: raise if raises is not None: exception_type = raises.get("type") message = raises.get("message") try: result.exception_was_raised(exception_type) exception_message = self._story_friendly_output( result.exception.message) self.assert_text(exception_message, message) except AssertionError: if self._rewrite: new_raises = raises.copy() new_raises["message"] = exception_message self.current_step.update(raises=new_raises) else: raise @validate(seconds=Int()) def sleep(self, seconds): time.sleep(int(seconds)) def on_success(self): if self._rewrite: self.new_story.save()
class Engine(BaseEngine): """Python engine for running tests.""" given_definition = GivenDefinition( setup=GivenProperty(Str()), code=GivenProperty(Str()), files=GivenProperty(MapPattern(Str(), Str())), postgres_version=GivenProperty(Str()), python_version=GivenProperty(Str()), ) def __init__(self, paths, settings): self.path = paths self.settings = settings def set_up(self): """Set up your applications and the test environment.""" self.path.cachestate = self.path.gen.joinpath("cachestate") self.path.state = self.path.gen.joinpath("state") self.path.working_dir = self.path.gen.joinpath("working") self.path.build_path = self.path.gen.joinpath("build_path") if self.path.state.exists(): self.path.state.rmtree(ignore_errors=True) self.path.state.mkdir() if self.path.build_path.exists(): self.path.build_path.rmtree(ignore_errors=True) self.path.build_path.mkdir() self.python = project_build(self.path, self.given["python version"]).bin.python if not self.path.cachestate.exists(): self.path.cachestate.mkdir() for filename, contents in self.given.get("files", {}).items(): filepath = self.path.state.joinpath(filename) if not filepath.dirname().exists(): filepath.dirname().makedirs() filepath.write_text(contents) if self.path.working_dir.exists(): self.path.working_dir.rmtree(ignore_errors=True) self.path.working_dir.mkdir() self.example_py_code = (ExamplePythonCode( self.python, self.path.state).with_setup_code(self.given.get( "setup", "")).with_terminal_size(160, 100).with_strings( postgres_version=self.given.get("postgres_version"), share=str(self.path.cachestate), build_path=str(self.path.build_path), )) def run(self, code): self.example_py_code.with_code(code).run() @no_stacktrace_for(AssertionError) def output_ends_with(self, contents): Templex(contents).assert_match(self.result.output.split("\n")[-1]) def write_file(self, filename, contents): self.path.state.joinpath(filename).write_text(contents) def raises_exception(self, message=None, exception_type=None): try: result = self.example_python_code.expect_exceptions().run( self.path.state, self.python) result.exception_was_raised(exception_type, message.strip()) except ExpectedExceptionMessageWasDifferent as error: if self.settings.get("rewrite"): self.current_step.update(message=error.actual_message) else: raise def file_contains(self, filename, contents): assert (self.path.working_dir.joinpath(filename).bytes().decode("utf8") == contents) @validate(duration=Float()) def sleep(self, duration): import time time.sleep(duration) def pause(self, message="Pause"): import IPython IPython.embed()