The right approach to integrated interaction with single testing

I had to start writing some unit tests using QualityTools.UnitTestFramework for the web service layer that we developed when my approach seemed wrong from the start.

It seems that unit tests should work in any order and not rely on other tests.

My initial thought was to have something similar to the following tests (a simplified example) that would work as an ordered test in the same order.

AddObject1SuccessTest
AddObject2WithSameUniqueCodeTest
(relies on the first test that created object1 first, and then waits for failure)
AddObject2SuccessTest
UpdateObject2WithSameUniqueCodeTest
(relies on the first test by creating object1 and thrid test, creating object2 first, and then fails)
UpdateObject2SuccessTest
GetObjectListTest
DeleteObjectsTest
(using the added identifiers)

However, between the tests there is no state and there is no visible way to transmit, for example, added identifiers to the deleted one.

So, does this mean that the right approach is to comprehensively test complex script interactions?

for instance

AddObjectSuccessTest
(which creates the object, gets it to validate the data, and then deletes it)
AddObjectWithSameUniqueCodeTest
(which creates object 1, then tries to create object 2 with an error, and then deletes object 1)
UpdateObjectWithSameUniqueCodeTest
(which creates object 1, then creates object 2, and then tries to update object 2 to have the same unique code as object 1 with an error, and then deletes object 1 and object 2)

Am I really wrong?

thanks

+4
source share
2 answers

This is the principle of unit testing, according to which each test case should be independent of any other test case. MSTest (as well as all other unit testing modules) provides this without guaranteeing the order in which the tests are executed - some (xUnit.NET) even go so far as to randomize the order between each test run.

It is also recommended that units be condensed into simple interactions. Although a hard and fast rule cannot be envisaged, it is not a unit test if the interaction is too complicated. In any case, complex tests are fragile and have very high overhead, so simple tests are preferred.

It looks like you have a case of shared state between your tests. This leads to interdependent trials and should be avoided. Instead, you can write reusable code that sets the precondition state for each test, ensuring that this state is always correct.

This precondition condition is called Fixture. The book xUnit Test Patterns contains a lot of information and recommendations for managing devices in different scenarios.

+5
source

In addition to what Mark said, yes, each test must be completely independent of the others, and to use your terms, each test must be a self-contained script that can work independently of the others.
I suppose from what you describe, that you check perseverance, because at your steps you have to delete the entities that you created at the end of the test to clear the state. Ideally, a unit test runs completely in memory, with no common state between each test. One way to achieve this is to use Mocks. I assume that you have something like a repository in place, so your class calls Repository.Add (myNewObject), which calls something like Repository.ValidateObjectCanBeAdded (myNewObject). Instead of testing a real repository that will add objects to the database and require deleting them to clear the state after the test, you can create an IRepository interface with two identical methods and use Mock to check when your class calls IRepository, it uses the correct methods with the right arguments in the correct order. It also gives you the ability to set a β€œfake” repository to any state you want in memory, without physically adding or deleting records from real storage.
Hope this helps!

+3
source

All Articles