I have a chunk of code that looks something like this:

function bool PassesBusinessRules()
    bool meetsBusinessRules = false;

    if (PassesBusinessRule1 
         && PassesBusinessRule2
         && PassesBusinessRule3)
         meetsBusinessRules= true;

    return meetsBusinessRules;

I believe there should be four unit tests for this particular function. Three to test each of the conditions in the if statement and ensure it returns false. And another test that makes sure the function returns true.

Question: Should there actually be ten unit tests instead? Nine that checks each of the possible failure paths. IE:

  • False False False
  • False False True
  • False True False

And so on for each possible combination.

I think that is overkill, but some of the other members on my team do not. The way I look at it is if BusinessRule1 fails then it should always return false, it doesn't matter if it was checked first or last.

  • Does the compiler use greedy evaluation for the && operator? Commented Jul 6, 2012 at 19:48
  • 15
    If you wrote 10 unit tests, you would be testing && operator, not your methods. Commented Jul 6, 2012 at 20:32
  • 2
    Wouldn't there only be eight tests if you tested all possible combinations? Three boolean parameters turned either on or off. Commented Jul 6, 2012 at 20:32
  • 4
    @Mert: Only if you can guarantee that the && will always be there.
    – Misko
    Commented Jul 6, 2012 at 21:55
  • 1
    I would test the intention. The intention is that conditions should be met to test to be null. This means setup all but one as true and create 3 tests with one as false each time.
    – regisbsb
    Commented Feb 15, 2014 at 23:47

9 Answers 9


Formally, those types of coverage have names.

First, there's predicate coverage: you want to have a test case that makes the if statement true, and one that makes it false. Having this coverage met is probably a basic requirement for a good test suite.

Then there Condition Coverage: Here you want to test that each sub-condition in the if has the value true and false. This obviously creates more tests, but it usually catches more bugs, so it's often a good idea to include in your test suite if you have time.

The most advanced coverage criteria is usually called Combinatorial Condition Coverage: Here the goal is to have a test case that goes through all possible combinations of boolean values in your test.

Is this better than simple predicate or condition coverage? In terms of coverage, of course. But it's not free. It comes at a a very high cost in test maintenance. For this reason, most people don't bother with full combinatorial coverage. Usually testing all branches (or all conditions), will be good enough for catching bugs. Adding the extra tests for combinatorial testing won't usually catch more bugs, but requires a lot of effort to create and maintain. The extra effort usually makes this not worth the very very small payoff, so I wouldn't recommend this.

Part of this decision should be based on how risky you think that code will be. If it has a lot of room to fail, it's worth testing. If it's somewhat stable, and won't change much, you should consider focusing your testing efforts elsewhere.

  • 2
    If the boolean values are passed from external sources (meaning they aren't always validated), then combinatorial conditional coverage is often necessary. First make a table of the combinations. Then, for each entry, decide if that entry represents a meaningful use case. If not, there should be code somewhere (either software assertions or validation clause) to prevent that combination from being executed. It is important not to lump all parameters in a single combinatorial test: try to partition parameters into groups that interact with each other i.e. shares the same boolean expression.
    – rwong
    Commented Jul 7, 2012 at 4:57
  • How certain are you of the bolded terms? Your answer seems to be the only occurence of "Combinatorial Condition Coverage", and some resources say that "predicate coverage" and "conditional coverage" are the same thing.
    – Stijn
    Commented Aug 18, 2016 at 12:52

Ultimately, it depends on you(r team), the code and the specific project environment. There is no universal rule. You(r team) should write as many tests as you need to feel comfortable that the code is indeed correct. So if your teammates aren't convinced by 4 tests, maybe you need more.

OTOH time to write unit tests is usually a scarce resource. So strive to find the best way to spend the limited time you have. E.g. if you have another important method with 0% coverage, it may be better to write a couple of unit tests to cover that one, rather than to add extra tests for this method. Of course, it also depends on how fragile the implementation of each is. Planning a lot of changes to this particular method in the foreseeable future may justify extra unit test coverage. So may being on a critical path inside the program. These are all factors which only you(r team) can assess.

I personally would usually be happy with the 4 tests you outline, that is:

  • true false false
  • false true false
  • false false true
  • true true true

plus maybe one:

  • true true false

to ensure that the only way to get a return value of true is to satisfy all 3 business rules. But in the end, if your teammates insist on having combinatorial paths covered, it may be cheaper to add those extra tests than to continue the argument a lot longer :-)


If you want to be safe, you would need eight unit tests using the conditions represented by a three variable truth table (http://teach.valdosta.edu/plmoch/MATH4161/Spring%202004/and_or_if_files/image006.gif).

You can never be sure that the business logic will always stipulate that the checks are performed in that order and you want the test to know as little about the actual implementation as possible.

  • 3
    Unit testing is white-box testing. Commented Jul 6, 2012 at 19:49
  • Well order should not matter, && is communitive, or at least should be
    – Zachary K
    Commented Feb 16, 2014 at 14:17

Yes, there should be the full combination in an ideal world.

When doing the unit test, you really should try to ignore how the method does its work. Simply provide the 3 inputs and verify that the output is correct.

  • 1
    Unit testing is white-box testing. And we don't live in an ideal world. Commented Jul 6, 2012 at 19:48
  • @PéterTörök - We don't live in an ideal world to be sure, but stackexchange disagrees with you on the other point. Especially for TDD, the tests are written to the specifications, not the implementation. I personally take 'specification' to include all inputs (including member variables) and all outputs (including side effects).
    – Telastyn
    Commented Jul 6, 2012 at 20:05
  • 1
    It's only one specific thread on StackOverflow, about a specific case, which shouldn't be overgeneralized. Especially as this current post is obviously about testing code which is already written. Commented Jul 6, 2012 at 20:53

State is evil. The following function does not need a unit test because it has no side effects and it is well understood what it does and what it does not do. Why test it? Do you not trust your own brain??? Static functions are great!

static function bool Foo(bool a, bool b, bool c)
    return a && b && c;
  • 4
    No, I don't trust my own brain - I learned the hard way to always double-check what I do :-) So I would still need unit tests to ensure that I haven't e.g. mistyped anything, and that noone is going to break the code in the future. And more unit tests to verify the caller method which calculates the state represented by a, b and c. You can move business logic around any way you want, in the end you still need to test it somewhere. Commented Jul 7, 2012 at 11:41
  • @Péter Török, you can also make typos in your tests and thus end up with false positives, so where do you stop? Do you write unit tests for your unit tests? I do not trust my brain 100% either, but at the end of the day writing code is what I do for a living. It is possible to have a bug inside this function but it is important to write code in such a manner that a bug will be easy to trace to the source and so that once you isolated the problem and have made a fix, you are better off. Well written code can rely on integration tests mostly infoq.com/presentations/Simple-Made-Easy
    – Job
    Commented Jul 9, 2012 at 3:37
  • 2
    Indeed the tests can be faulty too. (TDD adresses this by making the tests fail first.) However, making the same kind of error twice (and overlooking it) has a much lower probability. In general, no amount and type of testing can prove that the software is bug-free, just reduce the probability of bugs to an acceptable level. And in speed of tracing bugs to the source, IMO nothing can beat unit tests - fast feedback rulez :-) Commented Jul 9, 2012 at 8:50
  • "The following function does not need a unit test" I think you're being sarcastic here, but it's not clear. Do I trust my own brain? NO! Do I trust the brain of the next guy who touches the code? EVEN MORE NO! Do I trust that all the assumptions behind the code will be true a year from now? ...you get my drift. Also, static functions kill OO... if you want to do FP, then use an FP language.
    – sea-rob
    Commented Feb 16, 2014 at 7:12

This is one of those cases where Something like quickcheck (http://en.wikipedia.org/wiki/QuickCheck) will be your friend. Instead of writing out all N cases by hand have the computer generate all (or at least a large number) of possible test cases and validate that all return a sensible result.

We program computers for a living here, why not program the computer to generate your test cases for you?


You could refactor the conditions into guard conditions:

if (! PassesBusinessRule1) {
    return false;

if (! PassesBusinessRule2) {
    return false;

if (! PassesBusinessRule3) {
    return false;

I don't think that reduces the number of cases, but my experience is that it's easier to break them out this way.

(Note that I'm a big "single point of exit" fan, but I do make an exception for guard conditions. But there are other ways to structure the code so you don't have separate returns.)


I know this question is quite old. But I want to give another perspective to the problem.

First, your unit tests should have two purposes:

  1. Create documentation for you and your team mates, so after a given amount of time you could read the unit test and make sure you understand what's the class' intention and how the class is doing its work
  2. While developing, the unit test makes sure the code we are writing down is doing its work as it was intended in our mind.

So, recapitulating the problem, we want to test a complex if statement, for the given example, there are 2^3 possibilities, that is an important amount of tests we can write.

  • You can adapt to this fact and write down 8 tests or make use of parametrized tests
  • You can also follow the other answers and remember that the tests should be clear with the intention, this way we are not going to mess with too many details that in the near future may make harder to understand what is doing the code

On the other hand, if you are in the position that your tests are even more complex than the implementation, it's because the implementation should be redesigned (more or less depending on the case) rather than the test itself.

For the complex if statements, for example, you could think on chain responsability pattern, implementing each handler this way:

If some simple business rule apply, derive to the next handler

How simple would be to test various some simple rules, instead of a complex rule?

Hope it helps,


Unit tests should test your intentions. Not more, not less.

Your intention is to return a true, when and only when business rules 1, 2 and 3 are true. So the test cases would turn out to be:

  • Rules 1,2 and 3 being true => (true, true, true) returns true
  • One rule among the three being false, should return a false. Therefore, the cases are (false, true, true), (true, false, true) and (true, true, false). All of these should return false

Not the answer you're looking for? Browse other questions tagged or ask your own question.