igor.wojda
11/24/2021, 2:18 PMmutableListOf
) to create collections are quite handy, but I find them a bit painfull for testing:
class Bus {
private val persons = mutableSetOf<Person>()
fun addPerson(persons: Person) {
persons.add(person)
}
}
^ no easy way to test that person was added to the list.
We can always create a factory or pass in constructor, but I wonder how do you deal with that?
Is there anything better?Joffrey
11/24/2021, 2:19 PMno easy way to test that person was added to the listHow are those helpers different from any other kind of internal state in your class?
Joffrey
11/24/2021, 2:21 PMhow do you deal with that?Private state should be private. The class can be tested through its apparent behaviour via its public API. Everything private is an implementation detail that is irrelevant for testing. The classic question is "but how do you test the method
addPerson
then?", and the answer is you don't. You don't test methods, you test use cases of behaviour. So in this case I'd say your tests should consist of calls to addPerson
+ calls to whatever other methods are impacted by this state change, and they should assert that the sequence of calls behaves as expected. Repeat for as many use cases as you want to supportRoukanken
11/24/2021, 2:40 PMList<Int>.sum(): Int
which does the obvious
but (even if it was possible) I don't go and check "did this function iterate the whole list?", I only check if the result is correct (on multiple example lists)
If the function somehow sums up the list (correctly, every time) without iterating it then I don't care 🤷, only better for me, since it would be probably fasterephemient
11/24/2021, 5:21 PMcheckScenarios {
val list = mutableListOf<Int>()
var expectedSum = 0
ImperativeCommand { env ->
env.executeCommands(
constant(ImperativeCommand { env ->
val element = env.generateValue(integers(), null)
list += element
expectedSum += element
assertEquals(expectedSum, list.sum())
})
)
}
}
or simpler
forEach(listsOf(integers()) { it.sum() == it.fold(0, Int::plus) }
and it generates a hundreds of test cases for you. this helps keep you focused on testing the intended behavior of the subject, not its implementation, and can catch edge cases you didn't know you had