我理解关于单元测试的一般想法,并且已经在系统中发生复杂交互的场景中使用它,但我仍然对所有这些原则汇总在一起存在疑问。
我们被警告不要测试框架或数据库。良好的UI设计不适合非人体测试。一般来说,UI交互在MVC框架中被排除。在许多应用程序中还剩下什么? 37signals讨论了广泛的单元测试,但在像Basecamp或Backpack这样的应用程序中,通过适当的单元测试测试的内容究竟是什么类型? 100%的代码覆盖率在那种情况下意味着什么?
编辑:我没有拆掉像背包这样的应用程序 - 它们很棒,但是工作似乎更多地涉及设计和交互,而不是复杂的逻辑(事实上,他们支持这个想法)。在该应用程序的那些区域中,CRUD和哪个对象的层次结构几乎覆盖了它,单元测试的适当数量是零吗?在这种情况下,测试点是否是验证代码的另一个副本(必需,正则表达式等)?答案 0 :(得分:8)
商业应用的TDD就像这样。
写下业务要求。
记下该要求的测试。
编写通过测试的代码。
诀窍在于,有许多垃圾非业务需求不需要进行大量测试。
“保存到数据库”不是业务要求。这是技术性的。
“在某些情况下激活GUI上的按钮”不是业务要求,它是界面的一部分。
“备份”不是业务要求;它的安全性或业务连续性等等。
考虑一个具体的例子。
要求 - “在你支付罚款之前,你不能借书。”
测试。
尝试罚款借书。
尝试不用罚款借书。
代码。
class FinesNotPaid( unittest.TestCase ):
def setUp( self ):
# load some fixtures with users, books and fines outstanding.
def test_should_not_checkout_book( self ):
x = TheCheckoutClass()
x.checkoutBook( someBook )
self.fail( "Should have thrown error" )
class FinesPaid( unittest.TestCase ):
def setUp( self ):
# load some fixtures with users, books and fines paid.
def test_should_not_checkout_book( self ):
x = TheCheckoutClass()
x.checkoutBook( someBook )
self.success( )
class NoFines( unittest.TestCase ):
etc.
这些是由与数据库和GUI分开的类实现的业务规则。这些是应用程序域层中的类。
您的CRUD规则是业务规则。你需要测试它们。但是,您无需测试每个与数据库相关的功能。你需要一些“我可以创建和持久化对象吗?”试验。您必须相信ORM,数据访问层和数据库实际上是可行的。您不会编写测试来详尽地测试ORM的内置功能。</ p>
代码覆盖率(100%或80%或10%)在很大程度上毫无意义。具有80%代码覆盖率的测试的软件实际上更有可能失败20%吗?它不起作用。测试每行代码并不涵盖所有逻辑路径,因此请不要担心并开始测试。
测试业务用例。如果它们通过并且有未经测试的代码,那么 - 也许 - 你写了太多的代码。
答案 1 :(得分:2)
您正在进行测试,以确保业务逻辑(在许多应用中,这是“服务”或“逻辑”层)与业务用户对业务实际运作方式的描述相匹配。例如,您正在进行测试,以确保仅仅因为您向宾夕法尼亚州的所有商品中添加6%的销售税,当您向某人赠送礼品卡时,您也不会获得6%的奖励。
在UI和数据库之间的应用程序层中存在(或应该存在)大量脑汁。这就是测试出来的东西。