How do I efficiently unit test with case statements under BDD?
I'm relatively new to unit testing, and have become concerned by the fact that the quantity of my test code is dwarfing my production code when I have case statements where certain calls to external functions are repeated but with different arguments and subsequently different outcomes. After my questions is some javascript pseudocode (apologies if this is formatted incorrectly) for a public function called calculateDeltas. In the code below, populateDeltas is a private function that I am testing indirectly through the test for calculateDeltas.
The problems I'm struggling with are the following:
1. I'm testing calculateDeltas in 4 different ways to cover the 4 different branches. 2. In this way, I'm effectively testing populateDeltas 3 times. There are a handful of assertions for each test of populateDeltas and these tests are effectively being repeated 3 times w开发者_如何学JAVAith different arguments. 3. One thought I had was to test populateDeltas in isolation. In that case aren't I now testing implementation and, more importantly, how would I ever know the whole function calculateDeltas works if I'm never testing it as one whole unit? 4. Even if this is a good idea how does that simplify my test for calculateDeltas? I presume I would just verify somehow that populateDeltas was called. 5. In that case, how am I verifying that the output of calculateDeltas is what I actually expect in the context it was called? 6. In other words, how do I know calculateDeltas works without running integration tests on private functions? 7. Doesn't this all violate the spirit of BDD which is to guard external, as opposed, to internal behavior and populateDeltas represents internal behavior, while calculateDeltas represents external behavior?Thanks for any insight, I'm a bit lost. Code follows:
function calculateDeltas(){
var deltas = {status: this.rowStatus};
switch(this.rowStatus){
case 'new':
this.populateDeltas(deltas, 'new');
return deltas;
case 'changed':
deltas.key = this.key();
this.populateDeltas(deltas, 'changed');
return deltas;
case 'unchanged':
deltas.key = this.key();
this.populateDeltas(deltas, 'unchanged');
return deltas;
case 'deleted':
deltas.status = 'deleted';
return deltas;
}
There's nothing wrong with writing several tests to cover all scenarios.
If your concern is over testing the core logic, one approach for case statements is to replace conditional logic with a strategy pattern. In this scenario, I would have a class to handle the logic for each scenario and then put them in a lookup table. You end up with code that just executes the handler based on row status. You can easily test this logic once and then write specific tests for each handler.
In the code below, populateDeltas is a private function that I am testing indirectly through the test for calculateDeltas
This is often confusing.
It's important to note that private is not an essential tool. Public functions are fine. Really. Python folks are perfectly happy with nothing being private. We're all adults here.
Doesn't this all violate the spirit of BDD which is to guard external, as opposed, to internal behavior and populateDeltas represents internal behavior, while calculateDeltas represents external behavior?
While BDD is focused on external behavior, you made an implementation decision to create a private, shared function.
You can still do BDD and test this private, shared function. Just test all four cases. The external interfaces depend on this internal interface.
If you want to test the internals, that's okay. It's not BDD, it's just a good idea.
It's possible to have good ideas above and beyond the minimal baseline of good ideas that is BDD. You can add to BDD because of your implementation choice here.
In other words, how do I know calculateDeltas works without running integration tests on private functions?
This is a fairly silly question. Too much thinking. Just test the external interface. If the external function uses an internal, private function, then the external test will test the internal function in the normal course of events.
精彩评论