如何对业务规则进行单元测试?
我需要进行单元测试以确保我正确累积假期时间。 但是假期时间是根据业务规则累积的,如果规则发生变化,那么单元测试就会中断。
这是可以接受的吗? 我是否应该通过方法公开规则,然后从我的代码和测试中调用该方法以确保单元测试不那么脆弱?
我的问题是:对可能发生变化的业务规则进行单元测试的正确方法是什么?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您的测试应确保代码正确遵守业务规则。 因此,我不会编写围绕业务规则或依赖业务规则代码本身的测试。 相反,当业务规则发生变化时,我会首先更改测试以反映新的业务规则,然后当我的代码不再通过测试时,再去修复代码,使其通过测试。
您不希望发生的情况是编写测试,这样当您更改相同业务规则的应用方式时,您的测试就会中断。 说起来容易做起来难,但本质上您想要测试的是实现规则所需的最低限度,而不需要过于狭窄地规定代码的实现方式。 但是,如果规则的结果不同,那么您应该首先更改测试,然后更改代码以匹配它。
您也不希望测试与特定数据耦合。 假设在进行税收计算时,您的测试不应假设被测试的类使用 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.
我有类似的设置 - 但是我的业务规则已编译但具有可配置选项(您的可能不同)。 当业务规则改变其运行的核心方式时,我的单元测试就会失败。 这实际上是预料之中的——而且很好! 这意味着我可以隔离整个系统中的任何意外波动,并更新测试以匹配更改。
如果您的规则是外部的(某种脚本语言或数据库存储过程),那么您将需要将它们包装在集成测试中,并连接集成测试以自动执行。 虽然集成测试不再是单元测试,但它也相当重要,并且将以与单元测试相同的方式帮助您防止由于业务规则更改而产生意外的连锁反应。
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.
听起来好像您有业务规则,然后您就有这些业务规则的客户。 如果这两者可以独立变化,那么明智的做法是相应地设计您的 API。
正如所提出的,您的问题听起来可以通过适当使用策略模式来解决。 该策略代表您的业务规则,因此您可以在纯粹的上下文中对这些规则进行单元测试,而无需担心客户。
当业务规则发生变化时,简单地保留旧策略(以防以后再次需要它)并编写(和单元测试)代表新业务规则的全新策略可能更有意义。
当您完全完成新策略后,您可以在客户端中替换该策略。
在对客户端进行单元测试时,您应该针对测试双重策略(如模拟或存根)执行此操作,以验证客户端是否与策略正确交互,而不依赖于任何特定的策略实现。
通过这种方式,您可以清楚地分离关注点,并保持单元测试的可维护性。 您还遵守开放/封闭原则。
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.
如果规则改变,测试就会失败,这听起来是正确的——这是可以预料的。
如果您在测试本身中使用数据固定装置而不是硬编码值,则可以使将来更轻松地维护测试。 例如,如果您的方法应返回 foo,则可以将其放在固定装置中。 当您更改业务逻辑时,您只需更改固定装置,而无需执行单元测试本身。
当然,这很大程度上取决于您正在测试的逻辑类型,并且可能并不总是适用。
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.
我认为这是一个不正确的问题
业务规则和单元测试处于不同的抽象级别。
业务规则位于最高抽象级别(业务建模),但单元测试用于测试处于最低抽象级别的代码单元,因此您不能使用单元测试来验证或验证业务规则。
此外,分析和设计后的业务规则可能会影响多个代码单元,因此您不能使用单元测试来验证或验证业务规则。
我认为你可以使用测试用例或BDD场景来验证和验证业务规则。
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.