To draw aspects of a few answers together and add my 2p ...
Note: my comments relate to database testing particularly, and not UI testing (though obviously similar applies).
Databases are in just as much need of testing as front end applications but tend to get tested on the basis of 'does it work with the front end?' or 'do the reports produce the correct result?', which in my opinion is testing very late in the process of database development and not very robust.
We have a number of clients that utilise unit/integration/system testing for their data warehouse database in addition to the usual UAT/performance/et al. tests. They find that with a continuous integration and automated testing they pick up many problems before getting to traditional UAT, thus saving time in UAT and increasing the chance of UAT success.
I'm sure most would agree that a similar rigour should be applied to database testing as to front end or report testing.
The key thing with testing is to test small simple entities, ensuring their correctness, before proceeding onto complex combinations of entities, ensuring their correctness before expanding to the wider system.
So giving some context to my answer ...
Unit Testing
- has a testing focus to prove that unit works, e.g. a table, view, function, stored procedure
- should 'stub' the interfaces to remove external dependencies
- will provide its own data. You need a known starting state of data, so if there is a chance of data existing pre-test, then truncations/deletions should occur before population
- will run ideally in its own execution context
- will clear up after itself and remove the data it used; this is only important when stubs aren't used.
The advantages of doing this are that you are removing all external dependencies on the test and performing the smallest amount of testing to prove correctness. Obviously, these tests cannot be run on the production database. It may be that there are a number of types of tests you will do, depending on the type of unit, including:
- schema check, some might call this a 'data contract' test
- column values passing through
- the exercising of logic paths with different values of data for functions, procedures, views, calculated columns
- edge case testing - NULL, bad data, negative numbers, values that are too large
(Unit) Integration Testing
I found this SE post helpful in talking about various types of testing.
- has the testing focus to prove that units integrate together
- performed on a number of units together
- should 'stub' the interfaces to remove external dependencies
- will provide its own data, to remove the effects of outside data influences
- will run ideally in its own execution context
- will clear up after itself and remove the data created; this is only important when stubs aren't used.
In moving from unit tests to these integration tests, often there will be slightly more data, in order to test a wider variety of test cases. Obviously, these tests cannot be run on the production database.
This then proceeds onto System Testing, System Integration Testing (aka end-2-end testing), with increasing data volumes and increasing scope. All these tests should become part of a regression testing framework. Some of these tests might be chosen by the users to be performed as part of the UAT, but UAT is the tests defined by the users, not as defined by IT - a common problem!
So now that I have given some context, to answer your actual questions
- prepopulating data for unit and integration testing can cause spurious test errors and should be avoided.
- The only way to ensure consistent tests is to make no assumptions about the source data and control it rigorously.
- a separate test execution context is important, to ensure that one tester is not conflicting with another tester performing the same tests on a different branch of source controlled database code.