【问题标题】:Basic rules for unit test case writing [closed]单元测试用例编写的基本规则
【发布时间】:2014-09-11 11:49:55
【问题描述】:

我怀疑在我的 C# 应用程序中编写单元测试用例。我有一堂有 3 种方法的课程,例如

InsertEmp(int empid, string empname)
UpdateEmp(int empid, string empname)
SelectEmp(int empid)

我怀疑我们是否需要为所有 3 种方法编写单元测试用例?因为,当我使用一些测试数据为 InsertEmp 和 UpdateEmp 编写单元测试用例时,测试数据总是插入(或更新)到我的数据库中。

这有效吗?

【问题讨论】:

  • 这些看起来像是在做三种不同的事情,所以你需要测试三种不同的结果,对吧?
  • 是的,三个不同的结果
  • 所以...三种不同的设置,三种不同的调用,以及三种不同的成功测试。那么......三个测试用例?

标签: c# unit-testing


【解决方案1】:

嗯,你在测试什么?如果您正在与物理数据库交互,那么您不是单元测试,而是集成测试。持有这些方法的类是否与数据库紧密耦合,还是可以使用模拟数据库?

如果它可以使用模拟,则在实例化它时将该模拟提供给类并使用该模拟(或假的,或存根,有lots of subtle terminology)来验证对这些方法的调用是否导致与数据库。

如果它不能使用模拟并且与数据库紧密耦合,那么您就不能在与该数据库隔离的情况下对其进行单元测试。此时您有两种选择:

  1. 将其与数据库实现分离。
  2. 决定是否有逻辑值得单元测试。如果所有这些方法在内部都将插入/更新/选择命令委托给数据库,那么它们实际上不会任何需要进行单元测试的事情。 100% 的代码覆盖率很好,但在这种情况下您实际测试的是什么?

如果这个类在内部包含实际逻辑并且不仅仅是一个直接委托给数据库组件的包装器,那么它应该与该组件分离以用于测试目的。如果它不包含任何实际逻辑,我仍然会为实现 100% 覆盖率而鼓掌,但会将其放在优先级列表中的低位。

编辑:要考虑的另一件事是该特定对象如何适合您的整体业务运营。理想情况下,大部分被测试的逻辑是业务逻辑,与这些数据库命令无关。所以你的大部分测试都是模拟 this 对象来测试业务逻辑,而不是直接测试这个对象。

在这种情况下,您可以通过使用该对象(而不是模拟)来实现对业务逻辑操作的集成测试,从而实现该对象的代码覆盖(紧密耦合或其他方式)。也就是说,不是直接调用这个对象的方法,而是调用业务逻辑操作,它们自己调用这个对象的方法,有效地测试它。

无论如何,各个(原子)业务操作都应该在事务上隔离,因此您应该能够通过测试而无需提交工作单元。这将有效地测试这些,作为针对数据库的集成测试,而不会留下副作用。

【讨论】:

  • 请注意——回滚事务可能会产生意想不到的后果。例如,SQL Server 和 Oracle 都不会释放事务保留的自动增量/序列值。除非您稍后清理它们,否则您的表可能会意外地用完值。
  • @GalacticCowboy:可能是真的,但希望不会针对生产服务器执行测试......
  • 同意,但即使是非 prod 服务器也可能在遇到此类问题时中断业务。
  • @GalacticCowboy:如果非生产服务器正在中断业务,那么我认为“生产”的定义已经严重模糊,并且是一个更潜在的问题,超出了运行自动化测试。对于数据库的示例,完全删除和重新构建应该是按一下按钮(在测试场景中应该经常发生,也许作为定期安排的自动化集成测试的一部分)。
  • 任何执行测试的人都会有自己的实例。如果你能这样设置它,太棒了。甲骨文这样做的成本高得令人望而却步。因此,您通常会在多个人或组之间共享用于开发、QA 等的数据库。如果他们中的任何一个都可以通过单击按钮来炸毁该数据库,那将是一件大事。是的,我意识到数据抽象层的重点是解决这个问题——但这就是问题的重点。他没有这个抽象层,很多公司都没有。
猜你喜欢
  • 2019-04-15
  • 1970-01-01
  • 1970-01-01
  • 2018-04-04
  • 2015-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多