背景

当我们的测试数据是下面这些的时候,我们的用例是有问题的。

[
  {"name":"jack","password":"Iloverose"},
  {"name":"rose","password":"Ilovejack"}, {"name":"tom","password":"password123"}, {"name":"jerry","password":"password"} ] 

我们的用例只能找出tom是弱密码的用户,jerry这个用户会成为漏网之鱼。

为什么

这是因为在unittest中,一旦某个测试方法中的断言失败,后续的断言都不会被执行。

还原一下上面的例子,当用例在断言tom失败后,for循环就退出了,测试方法也执行完毕了,后面jerry这条数据就不会被断言。

怎么办

我们可以重构一下我们的用例,让整个用例只断言1次,断言失败以后就把弱密码的用户打印出来。

代码

修改user_data.json文件,加入一些测试数据,修改后的user_data.json文件应该是

[
  {"name":"jack","password":"Iloverose"},
  {"name":"rose","password":"Ilovejack"}, {"name":"tom","password":"password123"}, {"name":"jerry","password":"password"}, {"name":"fred","password":"123456"}, {"name":"elma","password":"654321"} ] 

新建test_password_4.py文件,内容如下


import unittest
import json

class WeakPasswordTeseCase1(unittest.TestCase):  @classmethod def setUpClass(kls): data_file_path = './user_data.json' print('before all test methods') with open(data_file_path) as f: kls.test_data = json.loads(f.read()) def test_week_password(self): res = True msg = [] for data in self.test_data: passwd = data['password'] tmp_res = True tmp_res = tmp_res and (len(passwd) >= 6) tmp_res = tmp_res and (passwd != 'password') tmp_res = tmp_res and (passwd != 'password123') if not tmp_res: msg.append("user %s has a weak password %s" %(data['name'], data['password'])) res = res and tmp_res self.assertTrue(res, "\n".join(msg)) def test_dummy(self): pass if __name__ == '__main__': unittest.main() 

运行及结果

在命令行中运行python test_password_4.py,结果如下

$ python test_password_4.py
before all test methods
.F
======================================================================
FAIL: test_week_password (__main__.WeakPasswordTeseCase1)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_password_4.py", line 27, in test_week_password self.assertTrue(res, "\n".join(msg)) AssertionError: user tom has a weak password password123 user jerry has a weak password password ---------------------------------------------------------------------- Ran 2 tests in 0.001s FAILED (failures=1) 

我们能学到什么

  • 断言一旦失败之后测试方法就会结束运行,所以一般来说1个测试方法推荐只有1个断言
  • 如果一个测试方法里面必须要有多个断言,那么要确保前面的断言失败之后,后面的断言就算不运行也不会影响测试的范围和结果
  • for循环中的断言一旦失败,for循环就退出了
  • 上面演示的测试用例写法其实具备了一定的数据驱动测试的思想