Skip to content

Commit

Permalink
Make unit tests runnable after functional tests in the same process.
Browse files Browse the repository at this point in the history
This fixes the raised in gabrielfalcao#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).
  • Loading branch information
tswicegood committed Jul 18, 2010
1 parent d6f2d2c commit 7f6e852
Showing 1 changed file with 33 additions and 14 deletions.
47 changes: 33 additions & 14 deletions tests/unit/test_step_runner.py
Expand Up @@ -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
Expand Down Expand Up @@ -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."
Expand All @@ -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."

Expand All @@ -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"

Expand All @@ -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"

Expand All @@ -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"

Expand All @@ -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"

Expand All @@ -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"

Expand All @@ -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 "(.*)"')
Expand All @@ -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<what>\w+) at "(?P<city>.*)"')
Expand All @@ -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<what>\w+)')
Expand All @@ -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"

Expand All @@ -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"

Expand All @@ -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. "

Expand Down

0 comments on commit 7f6e852

Please sign in to comment.