# 5. 实例: 找出所有是弱密码的用户




### 背景

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

```
[
  {"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```文件，内容如下

```python

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循环就退出了
* 上面演示的测试用例写法其实具备了一定的数据驱动测试的思想




原始封面

![课程图片](https://images.unsplash.com/photo-1512486130939-2c4f79935e4f?w=300)


