How to unit test business rules?
Asked Answered
P

5

5

I need a unit test to make sure I am accumulating vacation hours properly. But vacation hours accumulate according to a business rule, if the rule changes, then the unit test breaks.

Is this acceptable? Should I expose the rule through a method and then call that method from both my code and my test to ensure that the unit test isn't so fragile?

My question is: What is the right way to unit test business rules that may change?

Pulchritude answered 19/6, 2009 at 2:56 Comment(1)
When you change the rules, you change the expected results. That means that some positive unit tests that used to pass now fail, and some negative tests that used to pass (by detecting an error) may now fail (though this is usually less common). Unit tests can only validate the current rules - they cannot validate all changes to rules before the rules change. When the rules change, the unit tests may have to too.Mauricemauricio
L
5

Your tests should ensure that the code properly obeys the business rule. Therefore, I wouldn't write tests that go around the business rule or rely on the business rule code itself. Rather, when the business rule changes, I would first change the test to reflect the new business rule, then when my code no longer passes the test, go and fix the code so that it passes the test.

What you don't want to happen is to write your test so that when you change how the same business rule is applied, that your test breaks. That's easier said than done, but essentially what you want to test is the minimum required to implement the rule without dictating too narrowly how the code is implemented. If the outcome of the rule is different, though, then you should be changing the test first, then the code to match it.

You also don't want the test to be coupled to specific data, either. Say when doing a tax calculation, your test shouldn't be written to assume that the class under test uses 5% as the tax. Instead, you should write your test so that it supplies the tax percentage, and then checks that the calculation is done correctly. Presumably, you'll have a range of values to test to make sure that out of range values are caught as well. One result of this is that you'll have a better design as this will help you to avoid hard-coded values and make your production code more flexible to changes in data.

Lixiviate answered 19/6, 2009 at 3:19 Comment(0)
B
4

I have a similar setup - however my business rules are compiled but have configurable options (yours may differ). When a business rule changes a core way in which it operates, my unit tests break. This is actually expected - and good! It means that I can isolate any unexpected ripples throughout my system and update the tests to match the changes.

If your rules are external (some sort of script language or database sproc) then you will need to wrap them in an integration test and wire up your integration tests for automated execution. While no longer a unit test, integration tests are fairly important as well, and will help you in the same way as unit tests to prevent unexpected ripples due to a business rule change.

Ballyrag answered 19/6, 2009 at 3:2 Comment(0)
F
2

It sounds like you have business rules, and then you have clients of those business rules. If those two can vary independently, it would be wise to design your API accordingly.

As presented, your question sounds like it can be solved with appropriate use of the Strategy pattern. The Strategy represents your business rules, so you can unit test those in a pure context without worrying about the client.

When the business rule changes, it may make more sense to simply leave the old Strategy as is (in case you need it again later on), and write (and unit test) a completely new Strategy that represents the new business rule.

When you are completely done with the new Strategy, you can replace the Strategy in the client.

When unit testing the client, you should do that against a Test Double Strategy (like a Mock or Stub) to verify that the client interacts correctly with the Strategy without being dependent on any particular Strategy implementation.

In this way, you get clean separation of concerns and you keep your unit tests maintainable. You also obey the Open/Closed Principle.

Fuel answered 20/6, 2009 at 20:26 Comment(0)
B
0

It sounds correct that the test fails if the rules are changed - that is to be expected.

You can make it easier to maintain the test in the future if you use a data fixture instead of hardcoded values in the test itself. For example, if your method should return foo, you can have that in the fixture. When you change the business logic, you simply change the fixture and you won't have to go through the unit test itself.

Of course, this highly depends on the type of logic you are testing, and may not always be applicable.

Bonsai answered 19/6, 2009 at 3:18 Comment(0)
D
-1

I think it's an incorrect Question Business Rule and unit test are in different abstraction levels. Business rule is in the top level of abstraction (Business Modeling) but unit test is for testing a unit of code that is in lowest level of abstraction so you can't use unit test to validate or verify a business rule. In addition a business rule after analysis and design may affect on several unit of codes so again you can't use unit test to validate or verify a business rule. I think you can use test case or BDD Scenario to validate and verify a business rule.

Downpour answered 28/6, 2016 at 8:17 Comment(4)
This is totally wrong, by mocking the layers under the object applying business rule,you can totally isolate the business layer into a single unit and so unit test it.Spark
a business rule after analysis and design may affect on several unit of codes witch of them do you want to mock ? how do you make a pure implementation of a business rule?Downpour
Of course, but what's the point ? Having one huge test to maintain or single unit tests ?Spark
BDD witch is popular QC practice now is a good solution to test a BRDownpour

© 2022 - 2024 — McMap. All rights reserved.