I am currently writing Selenium 2 WebDriver tests for an ASP.NET MVC 2 website (the tests are written in C# and run with NUnit as the testrunner). I'm familiar with unit testing (and have written unit tests for this project as well). Therefore, I know that unit tests should each be self-contained (should leave the system in the same state that it started in, whether it passed or failed) and independent (order of the tests should not matter, and the tests can be run one at a time or as a full suite without getting different results).
I've been attempting to do this with my UI regression tests as well, but I've been running into cases where doing so seems like I'm doing a lot of repeating myself. For example, in testing the CRUD of something called, for example, a Product. The self-contained tests would go something like this (just listing the steps here, not code):
Test Log On:
- Setup: None.
- Test: Navigate to the Log On page, enter log on information, click submit, verify that log on and redirect was successful.
- Tear Down: Log off.
Test Create:
- Setup: Perform the logic from the Log On test.
- Test: Navigate to the Create Product page, fill in form values, submit, verify that product is created and redirect was successful.
- Tear down: Delete product, log off.
Test Update:
- Setup: Perform the logic from the Log On test and the logic from the Create test.
- Test: Navigate to the Edit Product page, change some values, submit, verify that the update was successful.
- Tear down: Delete product, log off.
Likewise for testing delete, log off, etc.
As you can see, there is a lot of duplication between tests - the actions that are completed as the "Test" part of one test are duplicated in the setup or tear down of other tests. It would reduce duplication greatly if, instead of making each test self-contained, the CRUD tests were always run together - first the log on test, then the create, the update, the delete, and finally the log off test. However, this obviously goes against the very core of unit testing.
Given how many websites are out there with basic CRUD operations, I imagine this situation must come up for a lot of developers. So my question is: what is best practice in this situation? Is it better to have a bunch of independent tests, which overlap one another to varying degrees in their set-up/tear-down code? Or, in the case of automated UI testing/regression testing, is it ok (or even preferable) to have tests depend on one another? Or as a third alternative, should all of the CRUD tests be rolled up in one giant CRUD test?
Or is there some approach that I don't know about that is better overall? I've read about things like PageObjects, but unless I'm missing something, PageObjects really just refactor common actions into stand-alone methods/classes (which I completely agree with for ease of code maintenance and DRY principles), but they don't change the fact that you are still calling the same bits of logic over and over again in setups and tear-downs, rather than logging in once, creating one product, updating one product, deleting one product, and logging off once.