好的,本节课我们要解决的就是 上节课我们拼好的json中的 各层级的result结果:
先来看我们当前的数据:
{'result': '', 'cases': [ {'case_id': 21, 'case_name': '大用例1', 'result_case': '', 'steps': [ {'step_id': 67, 'step_name': '调用A接口步骤', 'result_step': '', 'data': { 'request_data': '{"url": "http://127.0.0.1:8000/test_api_A", "method": "get", "api_body": "", "api_body_method": "none"}', 'response': '{"errcode": "0"}', 'assert_result': '{}' } } ] }, {'case_id': 22, 'case_name': '大用例2', 'result_case': '', 'steps': [ {'step_id': 68, 'step_name': '测试B接口步骤1', 'result_step': '', 'data': { 'request_data': '{"url": "http://127.0.0.1:8000/test_api_B", "method": "get", "api_body": "", "api_body_method": "none"}', 'response': '{"errcode": "0"}', 'assert_result': '{}' } }, {'step_id': 69, 'step_name': '测试B接口步骤2', 'result_step': '', 'data': { 'request_data': '{"url": "http://127.0.0.1:8000/test_api_B", "method": "get", "api_body": "", "api_body_method": "none"}', 'response': '{"errcode": "0"}', 'assert_result': '{}' } } ] } ] }
我们先来思考下:
最外层的resutl 是由谁决定的?当然是内层的result_case ,
而result_case又是由谁决定的呢?当然是自己内层的result_step,
那么result_step 又是由谁决定的呢?当然是内部的assert_result。
所以我们的开发思路,必然是从内向外逐步进展。
那就要先考虑这个最内部的assert_result。
我们先回顾下 这个断言结果,我们存入数据库的时候代码是怎么写的?
上面代码可以看出,每个step的断言,都是一个字典,key为这个断言的设置文本本身。值为 真 / 假 (True/False)
而我们的最终结果,无论哪一级,都不会关心key,只会关心value是否存在False
所以我们的result_step 要怎么确定?
当然是遍历这个assert_result ,只要保证它内部没有False值,那么result_step就是True !
但是这个assert_result又是什么呢?原来它是tmp_assert_result的 json 字符串...
所以我们要遍历它的话,就只能先给它恢复成字典。
所以代码如下:
上图中,我们遍历了这个字典,判断内部是否有False , 只要发现一个False,我们就会给tmp_step["result_step"] 立即变成False, 并且终止循环,因为已经无需再测了。
如果一直到循环结束,都没有发现False, 那么就可以给tmp_step["result_step"]光荣的写成True了。
然后我们继续思考下一个问题。
如果这个s_report.assert_result 为空呢?也就是说这个接口步骤压根没有任何断言。
那么我们应该理所应当的,给tmp_step["result_step"] 写成True了。所以要在这个for 外面裹上一层判断if:
注意,这个if, 我并没有简单的写成 == ‘’ ,而是写成了 in [None,'',' ']
这样的好处是可以增加很大的容错性,因为我也害怕数据库因为某些意外存的并不是空字符串,而是None空型或者 其他纯空格什么的... 以后如果发现其他异常的参数,都可以写到这个列表中,更方便。
好,到这里我们搞定了这个step层级的result,然后继续往外搞result_case:
这里我们要思考下在哪里写这个判断代码,按理说应该是循环steps,判断其中的result_step是否有false, 来判断result_case的结果。
但是这样做显然需要额外一个for循环,会严重拖慢速度,那么有什么简单的方式呢?
当然有,而且很多。
比如,我们给result_case 一开始就默认设置成True ,然后如果发现result_step有False,则给result_case 再改成False不迟。 这样代码量会大大减少,而且没有额外增加循环:
其实这个道理 可以应用在任何层级上。就连我们刚刚写的result_step的值 也可以先变成True,然后查到一个assert_result[i] 为False 再改不迟。但是既然已经写完了,就算了。
我们继续往外写,最外层的结果:
res["result"]
这个的道理我们同样,可以给先变成True, :
改成这样后,我们就可以测试了:之前的大用例,虽然有俩个,但是很明显,我们没有给任何step加断言,所以结果一定是成功的。显示如下:
'cases': [{'case_id': 21, 'case_name': '大用例1', 'result_case': True, 'steps': [{'step_id': 67, 'step_name': '调用A接口步骤', 'result_step': True, 'data': {'request_data': '{"url": "http://127.0.0.1:8000/test_api_A", "method": "get", "api_body": "", "api_body_method": "none"}', 'response': '{"errcode": "0"}', 'assert_result': '{}'}}]}, {'case_id': 22, 'case_name': '大用例2', 'result_case': True, 'steps': [{'step_id': 68, 'step_name': '测试B接口步骤1', 'result_step': True, 'data': {'request_data': '{"url": "http://127.0.0.1:8000/test_api_B", "method": "get", "api_body": "", "api_body_method": "none"}', 'response': '{"errcode": "0"}', 'assert_result': '{}'}}, {'step_id': 69, 'step_name': '测试B接口步骤2', 'result_step': True, 'data': {'request_data': '{"url": "http://127.0.0.1:8000/test_api_B", "method": "get", "api_body": "", "api_body_method": "none"}', 'response': '{"errcode": "0"}', 'assert_result': '{}'}}]}]}
看到了吧。不过我们现在要在第二个大用例的第二个步骤的断言中 手动写个False, 来测试一下:
测试结果 出现错误!!!
我们来看这段代码:
大家发现我挖的坑了么?
s_report.assert_result 只是个字符串json, 没法用[i]的方式拿到里面的值,而我们前面for中的 是用了json.loads() ,所以这里我们需要改成:
这样大家印象深刻了么?json只不过是个字符串哦~
那报错到底说的什么意思呢?说的是:
“字符串的下标必须是整形!”
原来系统把我们[i] 当成是求下标了,其实我们是求字典的值哦,所以i 并不是整形而是某个字符串....
好了明白之后修复好我们再次测试:
这次就有了结果了,方便大家查看,我再次加几个回车展示给大家:
{'result': False, 'cases': [ {'case_id': 21, 'case_name': '大用例1', 'result_case': True, 'steps': [{'step_id': 67, 'step_name': '调用A接口步骤', 'result_step': True, 'data': {'request_data': '{"url": "http://127.0.0.1:8000/test_api_A", "method": "get", "api_body": "", "api_body_method": "none"}', 'response': '{"errcode": "0"}', 'assert_result': '{}'}}]}, {'case_id': 22, 'case_name': '大用例2', 'result_case': False, 'steps': [{'step_id': 68, 'step_name': '测试B接口步骤1', 'result_step': True, 'data': {'request_data': '{"url": "http://127.0.0.1:8000/test_api_B", "method": "get", "api_body": "", "api_body_method": "none"}', 'response': '{"errcode": "0"}', 'assert_result': '{}'}}, {'step_id': 69, 'step_name': '测试B接口步骤2', 'result_step': False, 'data': {'request_data': '{"url": "http://127.0.0.1:8000/test_api_B", "method": "get", "api_body": "", "api_body_method": "none"}', 'response': '{"errcode": "0"}', 'assert_result': '{"aaa":false}'}}]}]}
我们的预期,就是第二个用例的第二个步骤 出错,导致第二个用例也是错的,导致最终结果是错的。
但是第一个用例和内部的step都是无辜的,所以仍然保持True 。
好了,结果完美成功,本节课到此结束,欢迎关注下节课。
下节课我们就要开始写个前端报告页面了。来使用这套数据展示。
欢迎关注:测试开发干货