I have found multiple ways of looking at this:
- behaviour vs methods
- behaviour vs state
- behaviour vs implementation
(1) Unit-Test Behaviour, Not Methods
focus on the features that the object under test should provide,
We need to know how to use the class to achieve a goal, not how to exercise all the paths through its code.
Describing Behavior, Not API Features
We need to know how to use the class to achieve a goal, not how to exercise all the paths through its code.
(src: Book: Growing Object Oriented Software, Guided By Tests - Steve Freeman & Nat Pryce)
So behaviour here is the protocol, instead of the interface (Model: interface vs protocol)
(2) Test behaviour instead of state Another way of looking at it, is say ’test behaviour’ means
- test the behaviour like a user would use it
- or
- test the system as it would be used
instead of:
@Test cannot_create_duplicate_users() {
// arrange
...
var user = new User("a name")
userRepository.add(user)
// act
var secondUser = createUser("a name")
// assert
expect(secondUser).toBeNull()
expect(userRepository.users.filter(name ~= "a name")).toBe(user)
}
do this:
@Test cannot_create_duplicate_users() {
// arrange
...
// act
createUser("a name")
createUser("a name")
// assert
expect(DuplicateUsernameNotAllowed)
}
The first ’tests the implementation' The second ’tests the behaviour'
With the second, you test the behaviour of the system. ‘registering a user with the same name twice is not allowed’
With the first, you test ‘if there is already a user with that name, you cannot create another user with that same name’
(3) Test behaviour instead of implementation
I have heard this phrase often. I have used it occasionally. But right now, it’s still pretty vague to me.