I'm trying to create a new set of tests for testing a legacy web site that I'm working on. The site uses a database at the back end. I'm planning on using SpecFlow and Selenium, however I'm a bit stumped on what the best way to deal with cleaning up data is.
Currently I have a database backup with a set of sample data which I restore before each test run. This however is cumbersome so I would like to only do this for critical test runs before a release and leave the continuous integration runs working on the same database in between.
Currently I have a large number of tests that go something like this:
Secenario: Test Item Creation
Given I am logged in
When I create an item with a unique name
Then an item exists with the unique name
The when step uses a GUID to ensure the name is unique and the then step has access to this via a module variable to check that it exists.
Like I said however I have a lot of tests similar to this and I'm running them multiple times on the same database so the test system is getting stuffed full of items which is slowing down searches and the like.
My question is what is the best way to deal with this? Should I create another step in the test that deletes the item again like this:
Secenario: Test Item Creation
Given I am logged in
When I create an item with a unique name
Then an item exists with the unique name
Then delete the item with the unique name
Or should my test framework somehow be able to deal with this? If so what do people do? Given SpecFlow step's global nature I'd imagine that getting the teardown steps in the correct order if multiple items with parent-child relationships could become problematic.
A good test should have no dependencies, so having test steps create and then "tear down" test data is a good idea.
One approach you could take is to store the unique name generated by:
When I create an item with a unique name
in the ScenarioContext object e.g.
ScenarioContext.Current["testItem"] = "testItemName";
This will allow you to persist this value for the duration of the scenario.
You could then create a SpecFlow hook associated with a specific tag to tear-down this data when the scenario completes e.g. The scenario would be (note the tag):
@deleteTestItem
Secenario: Test Item Creation
Given I am logged in
When I create an item with a unique name
Then an item has exists with the unique name
And the code to clean up would be:
[AfterScenario("deleteTestItem")]
public void DeleteTestItem()
{
var testItemName = ScenarioContext.Current["testItemName"];
// Use testItemName to clean-up your database
}
This code will then only be run for scenarios which have this tag. Note that if all your tests involved creating a test item, then you could omit the tag and simply use an AfterScenario hook.
Alternatively you could persist all of the test item names in the FeatureContext, and then delete these items in an AfterFeature hook. This would lead to less database calls (i.e. you would not be calling the database to clean-up after every scenario).
I prefer the ScenarioContext approach as I feel that if a Scenario creates data, then that scenario should be responsible for cleaning-up after itself.