junit断言模糊匹配
正如在其他测试气味中所讨论的,例如“ 按竞争计算进行跟踪”以及“ 昨天通过” ,很容易创建晦涩的断言,这些断言要么不可靠,要么证明量不大。
尽管通常有很多“不好的理由”说明为什么我们不能编写简单明了的断言,但是认识到何时不编写断言,并尽力而为地朝着规范前进是一个非常好的主意。
让我们看一下虚构语言的测试:
// Note - this is is no specific language test( 'adding user to database results in new user' , {
user = createUser( 'John' , 'Smith' )
id = system.addUser(user)
readUser = system.retrieveUser(id)
assert (user.firstName).is( 'John' )
assert (user.lastName).is( 'Smith' ) });
上面具有简单测试的许多属性:
- 我们正在使用“ John”和“ Smith”的测试数据非常简单,就在我们眼前
- 作为API的被测系统适用于测试
- 我们使用精确的离散值来断言,这些值可以在测试之前进行预测
- 任何自动生成的内容(例如id以及userCreationDate (未显示))都不会影响我们的测试
但是关于…?
在上面的示例中,暗示可能为用户提供了id以及创建时间戳。
尝试编写这样的断言可能是一种诱惑:
readUser = system.retrieveUser(id)
assert (user).is(expectedUser)
凡expectedUser莫名其妙地被设置为包含用户,该系统将产生的完全匹配。
一般提示-如果在测试中有一个构造对象称为“预期”,则通过竞争性计算进行审判的风险很高。
为了实现预测系统生成的事物的能力,我们最终不得不将自己的密钥生成器和模拟时钟等插入系统。 这可能很有价值,或者可能是大量的测试垃圾。
让我们模糊匹配
整个对象匹配的替代方法是创建如下所示的内容:
// still a fictional language
readUser = system.retrieveUser(id)
assert (user).matches([
{ obj.firstName == 'John' },
{ obj.lastName == 'Smith' },
{ obj.id instanceof UUID },
{ obj.creationDate - now() < inSeconds( 5 ) }
])
在此组合测试中,有一些具体的断言,然后有更多的模糊断言。
模糊匹配很麻烦
上面的解决方案说明了如何对对象类型,近似的对象值进行相对有意义的断言,甚至可以对字段的内容进行正则表达式匹配……它允许您断言无法预测的值……
但…
上面的断言之所以大,是因为我们正在对无法完全匹配的对象进行整个对象匹配。
这可能是最好的选择。
备择方案
- 在单独的测试中一次进行模糊匹配,一次只进行一次–避免整个对象进行模糊匹配
- 筛选出无法与比较数据匹配的字段-通过消隐,从实际复制到预期或通过比较中的排除规则
- 装配发电机以产生可预测的值
- 编写可以预测值的较低级别的测试,因此您不必在较高级别上依赖模糊匹配
结论
在我们的断言中使用模糊匹配是能够拉动的一个好技巧,但是当没有其他方法可用时,它必须是最后的选择。
对整个有效载荷进行断言通常会使我们面临模糊匹配问题。
更精确的下层字段匹配可以消除对模糊性的需求。
翻译自: https://www.javacodegeeks.com/2019/11/fuzzy-assertions.html
junit断言模糊匹配