0

I have a validation method like this

def validate(a, b, c, d, e, f): Boolean = {
  val rs1 = check1(a, b)
  val rs2 = check2(c, d)
  val rs3 = check3(e, f)

  rs1 && rs2 && rs3
}

I have tests for all of the smaller methods check1, check2, and check3 and I want to test the big method validate also. But to test it, I imagine I have to write tests for all of the cases like:

  • all 3 checks succeed
  • check1 fails
  • check2 fails
  • ...

not to mention I will have to provide suitable sets of parameters (a, b, ...).

So what is the best practice for this situation or should I just skip testing the validate method?

Minh Thai
  • 141

3 Answers3

1

I have tests for all of the smaller methods check1, check2, and check3...

That is the cause of your current problems. check1 etc are implementation details of validate, so should only be tested via testing validate. So change those existing tests to use validate. That gives you that "suitable sets of parameters (a, b, ...)".

All that's then left to do is to test that it only validates when all checks pass.

David Arno
  • 39,599
  • 9
  • 94
  • 129
0

Test things that could go wrong. So maybe, writing tests for this method would not have much value. It is very simple code, and unlikely to be incorrect. The most likely source of errors is that you are passing the wrong arguments to the check() functions. If you are using a statically typed language, that risk is already reduced.

Note that a single test case (regardless of validation result) is sufficient to provide 100% statement, branch, and path coverage for this implementation of the validation() function when viewed in isolation. However, it does not provide full condition coverage. So writing at least one test case may be desirable. Maybe adding a second test case would also be good, so that you have one successful and one failing validation result.

Beyond that, testing for 100% condition coverage takes increasing amounts of effort for decreasing value. Unless correctness of the method is extremely important (e.g. a failure could cause permanent harm to users and/or would be very costly) this doesn't seem important. To test this method comprehensively, it may be desirable to rewrite your tests of checkX() functions as tests of the validate() function. This may result in less total effort than writing 3+1 additional tests where you have one test where all checks succeed, and one test per check where that check fails. Also, some people dislike white-box techniques like creating test cases to reach some coverage goal instead of using test cases to express requirements.

amon
  • 135,795
-2

I think that this Validate() method is potentially violating the Single Responsibility Principle. According to the SRP, "A class should have one reason to change". Here, we have three reasons to change. Thus, we are violating SRP. I think that's your main problem here.

To refactor this, I would extract check1() check2() and check3() into their own classes, unit test them separately, then inject them into the main validator class. After doing that, I would mock out Check1Validator, Check2Validator, and Check3Validator. The only thing to test now would be the invalid input of validate(), and the condition rs1 && rs2 && rs3.

Vin Shahrdar
  • 495
  • 4
  • 6