From 7f6e852febed135fd5d15081facdfa05c8010823 Mon Sep 17 00:00:00 2001 From: Travis Swicegood Date: Sun, 18 Jul 2010 18:31:51 -0500 Subject: [PATCH] Make unit tests runnable after functional tests in the same process. This fixes the raised in #52 where the unit tests would not pass if run in the same process and after functional tests were run (the default way that nosetests run thems). This commit fixes that. The registries are cleared and only the desired steps are defined. The issue at hand is the global `STEP_REGISTRY`, while a good idea, it was in an invalid state because of the way nosetests loads, then runs code. All test modules were being loaded into memory and the various steps were being defined inside tests.unit.test_step_runner. Once the tests started running, the tests in tests.functional.test_runner with `prepare_std*` setup methods were blowing away the steps that were stored in the `STEP_REGISTRY`. *NOTE*: This still wouldn't be thread safe (so far as I know) if you were to try to run all of the test methods in parallel you'd end up with each one of them trying to kill and setup the correct environment. There are ways to fix that, but they add additional complexity for something that's not widely done inside the Python community (yet, at least). --- tests/unit/test_step_runner.py | 47 ++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/tests/unit/test_step_runner.py b/tests/unit/test_step_runner.py index 7ab1521f9..54178b305 100644 --- a/tests/unit/test_step_runner.py +++ b/tests/unit/test_step_runner.py @@ -20,7 +20,7 @@ from lettuce import registry from lettuce.core import Step from lettuce.core import Feature -from nose.tools import assert_equals +from nose.tools import assert_equals, with_setup FEATURE1 = """ Feature: Count steps ran @@ -92,22 +92,29 @@ Then this step will be skipped """ -@step('I have a defined step') -def have_a_defined_step(*args, **kw): - assert True +def step_runner_environ(): + "Make sure the test environment is what is expected" -@step('other step fails') -def and_another(*args, **kw): - assert False, 'It should fail' + from lettuce import registry + registry.clear() -@step("define a step") -def define_a_step(*args, **kw): - assert True + @step('I have a defined step') + def have_a_defined_step(*args, **kw): + assert True -@step(u'When I have a step that raises an exception') -def raises_exception(step): - raise Exception() + @step('other step fails') + def and_another(*args, **kw): + assert False, 'It should fail' + @step("define a step") + def define_a_step(*args, **kw): + assert True + + @step(u'When I have a step that raises an exception') + def raises_exception(step): + raise Exception() + +@with_setup(step_runner_environ) def test_can_count_steps_and_its_states(): "The scenario result has the steps passed, failed and skipped steps. " \ "And total steps as well." @@ -122,6 +129,7 @@ def test_can_count_steps_and_its_states(): assert_equals(len(scenario_result.steps_skipped), 1) assert_equals(scenario_result.total_steps, 4) +@with_setup(step_runner_environ) def test_can_point_undefined_steps(): "The scenario result has also the undefined steps." @@ -138,6 +146,7 @@ def test_can_point_undefined_steps(): assert_equals(undefined1.sentence, 'Then this one has no definition') assert_equals(undefined2.sentence, 'And this one also') +@with_setup(step_runner_environ) def test_can_figure_out_why_has_failed(): "It can figure out why the test has failed" @@ -152,6 +161,7 @@ def test_can_figure_out_why_has_failed(): assert 'AssertionError: It should fail' in failed_step.why.traceback assert_equals(type(failed_step.why.exception), AssertionError) +@with_setup(step_runner_environ) def test_skipped_steps_can_be_retrieved_as_steps(): "Skipped steps can be retrieved as steps" @@ -161,6 +171,7 @@ def test_skipped_steps_can_be_retrieved_as_steps(): for step in scenario_result.steps_skipped: assert_equals(type(step), Step) +@with_setup(step_runner_environ) def test_ignore_case_on_step_definitions(): "By default lettuce ignore case on step definitions" @@ -171,6 +182,7 @@ def test_ignore_case_on_step_definitions(): assert_equals(scenario_result.total_steps, 3) assert all([s.has_definition for s in scenario_result.scenario.steps]) +@with_setup(step_runner_environ) def test_doesnt_ignore_case(): "Lettuce can, optionally consider case on step definitions" @@ -182,6 +194,7 @@ def test_doesnt_ignore_case(): assert_equals(scenario_result.total_steps, 3) assert not all([s.has_definition for s in scenario_result.scenario.steps]) +@with_setup(step_runner_environ) def test_steps_are_aware_of_its_definitions(): "Steps are aware of its definitions line numbers and file names" @@ -194,9 +207,10 @@ def test_steps_are_aware_of_its_definitions(): step1 = scenario_result.steps_passed[0] - assert_equals(step1.defined_at.line, 96) + assert_equals(step1.defined_at.line, 102) assert_equals(step1.defined_at.file, core.fs.relpath(__file__.rstrip("c"))) +@with_setup(step_runner_environ) def test_steps_that_match_groups_takes_them_as_parameters(): "Steps that match groups takes them as parameters" @step(r'Given a ([^\s]+) called "(.*)"') @@ -210,6 +224,7 @@ def given_what_named(step, what, name): assert_equals(len(scenario_result.steps_passed), 1) assert_equals(scenario_result.total_steps, 1) +@with_setup(step_runner_environ) def test_steps_that_match_named_groups_takes_them_as_parameters(): "Steps that match named groups takes them as parameters" @step(r'When a (?P\w+) at "(?P.*)"') @@ -223,6 +238,7 @@ def given_action_named(step, what, city): assert_equals(len(scenario_result.steps_passed), 1) assert_equals(scenario_result.total_steps, 1) +@with_setup(step_runner_environ) def test_steps_that_match_groups_and_named_groups_takes_just_named_as_params(): "Steps that match groups and named groups takes just the named as parameters" @step(r'(he|she) gets a (?P\w+)') @@ -235,6 +251,7 @@ def given_action_named(step, what): assert_equals(len(scenario_result.steps_passed), 1) assert_equals(scenario_result.total_steps, 1) +@with_setup(step_runner_environ) def test_step_definitions_takes_the_step_object_as_first_argument(): "Step definitions takes step object as first argument" @@ -254,6 +271,7 @@ def when_i_define_this_one(step): assert_equals(len(scenario_result.steps_passed), 1) assert_equals(scenario_result.total_steps, 1) +@with_setup(step_runner_environ) def test_feature_can_run_only_specified_scenarios(): "Features can run only specified scenarios, by index + 1" @@ -268,6 +286,7 @@ def just_register(scenario): assert_equals(scenarios_ran, ['2nd one', '5th one']) +@with_setup(step_runner_environ) def test_count_raised_exceptions_as_failing_steps(): "When a step definition raises an exception, it is marked as a failed step. "