How to test sequential logic individually?

Suppose I have a Car class with the following methods:

  • LoadGasoline (gas IFuel)
  • InsertKey (IKey key)
  • StartEngine ()
  • IDrivingSession Go ()

Car's goal is to configure and return the IDrivingSession, which the rest of the application uses to drive the car. How can I check my car?

It seems like this requires a sequence of operations before I can call the Go () method. But I want to test each method separately, since they all have some important logic. I don't want to have a bunch of unit tests like

Test1: LoadGasoline, Assert Test2: LoadGasoline, InsertKey, Assert Test3: LoadGasoline, InsertKey, StartEngine, Assert Test4: LoadGasoline, InsertKey, StartEngine, Go, Assert 

Is there a better way to modulate sequential logic or is it a car design issue?

--- EDIT ---- Thanks for all the answers. As many have noticed, I should also have tests for invalid scenarios, and I also have those, but this question focuses on how to check the correct sequence.

+4
source share
6 answers

I think that each method should be tested separately and independently.

IMHO, you have to prepare the environment for each case, so only the LoadGasoline test will be broken if you change the LoadGasoline method and you do not need to see that all tests are interrupted due to one error.

I don’t know what the state of your car looks like, but before InsertKey you should prepare using the car.SetTotalGasoline (20) method; or any variable is set in this method, but does not depend on the complex logic of the LoadGasoline method.

You will need a test (in this case, not a unit test) to check the entire sequence.

+3
source

Some unit testing modules allow you to specify a setup code that runs before the actual test begins.

This allows you to get the target in the correct state before running the test. Thus, your test may fail or fail based on the specific code you are testing, and not on the code necessary before you can run the test.

As a result, your test sequence will end approximately like this:

 Test1: LoadGasoline, Assert Test2 Setup: LoadGasoline Test2: InsertKey, Assert Test3 Setup: LoadGasoline, InsertKey Test3: StartEngine, Assert Test4 Setup: LoadGasoline, InsertKey, StartEngine Test4: Go, Assert 

Actually, since all tests are performed sequentially, there is no chance that Test Setup will fail if the previous test passes.

With that said, you should also check for failures that shouldn't work, but that is another problem.

+2
source

Why don't you need all these tests?

Go has a completely different behavior if you call it before or after, say, InsertKey , right? Therefore, in my opinion, you should test both behaviors.

+1
source

Its just reluctance, but sometimes this is what you need to do. If you cannot fake the system under test, so it thinks about it in a later state, then you need to go through the same steps to get into this state. Not knowing anymore that your testing is not clear how you could fake various states.

One way you can make this portable is to use the extract method refactoring when checking for one state so that the same code can be used to prepare the next test.

+1
source

I would suggest that

 Test 1: LoadGasoline, Assert, InsertKey Assert, StartEngine Assert, Go Assert Test 2: LoadGasoline, Go, Assert Test 3: Go, Assert Test 4: StartEngine, Go, Assert 

Depending on the actual object, I wouldn’t give a damn try and do all the permutations, but I would have one test that beats the success track, then I would have tests that hit my business with a fringe.

Edit:

After some thought, I might have tests like:

  • Run a car key that has no gas
  • Run the car with gas and the wrong key
  • Start the car with gas and the right key (test 1 above)
  • Press Peddle before starting the car.
+1
source

Technically, you should use the following tests at a minimum:

 testLoadGasoline testInsertKeyGasolineNotLoaded testStartEngineKeyNotInserted testGoEngineNotStarted testGo 

If you can directly view the intermediate steps, you can add

 testInsertKeyGasolineLoaded testStartEngineKeyInserted 

Please note that if you can directly set the state (which depends on the language and design), then testInsertKeyGasolineLoaded cannot actually call LoadGasoline .

0
source

Source: https://habr.com/ru/post/1285910/


All Articles