前言
作为一个测试新人,刚开始接触测试,对于怎么写测试用例很头疼,无法接触需求,只能根据站在用户的角度去做测试,但是这样情况会导致不能全方位的测试APP,这种情况就需要一份测试用例了,但是不会写,求指教!还有就是测试出来的bug该如何追踪?与开发的接触基本上面对面的交流,没有很好的一个规范
一、什么是测试用例
测试用例:为了特定的目的(证明软件存在某问题)而设计的一组由测试输入、执行条件、预期结果构成的文档
1、测试用例简单来说就是指导如何做测试的文档,该文档主要记录需要验证被测软件的是否满足需求
2、测试用例表现形式常见的有两种,可以以模板形式展示
1)一种是通过Excel直接编写
——大多数项目中都需要按照这种方式设计编写
2)一种是通过xmind直接整理测试点
——时间紧迫,项目没有强制要求时,可以设计测试点的形式编写
——对于业务流程类的测试,也可以整理为测试点进行测试
3、设计及执行人员:测试工程师
4、用例的模板:描述编写用例核心内容,一般项目都有自己的设计用例的模板
二.为什么要写测试用例
为什么要写测试用例,实际中产品出现问题,第一责任人首先想到的是测试为啥没有测到?
产品出现问题了,你为啥没有测出来呢?
当然,除了避免“甩锅和背锅”,其实写测试用例更重要的作用如下:
技术上将需求转化为具体可验证的指标
以文档的形式记录软件可能存在的问题
防止测试过程的活动出现遗漏,提高工作效率
测试工作量的展示
三.如何编写测试用例
既然写测试用例如此重要,那么如何更好的编写测试用例呢?个人认为需要满足如下几点: - 常规思考,设身处地的从用户角度出发(比如:实际用户是这么使用的么,会不会遇到异常情况呢?) - 测试理论方法的支撑(比如:根据需求设计测试用例时,能用到哪些常见的测试用例设计方法?) - 产品的熟悉和经验的积累(比如:已经有过类型项目经验,曾经在某个方面有过问题,当时是如何处理的呢?) 上述的设计用例过程,有个前提,就是对于测试有耐心和毅力,加上日常有意识的思维训练,才会写出全面的用例
测试函数
首先是给出用于测试的代码,如下所示,这是一个接收姓和名然后返回整洁的姓名的函数:
def get_formatted_name(first, last):
full_name = first + ' ' + last
return full_name.title()
简单的测试代码:
first = 'kobe'
last = 'bryant'
print(get_formatted_name(first, last)) # 输出 Kobe Bryant
在 Python 标准库中的模块 unittest 提供了代码测试工具。这里介绍几个名词的含义:
单元测试:用于核实函数的某个方面没有问题;
测试用例:一组单元测试,它们一起核实函数在各种情形下的行为符合要求。
全覆盖式测试用例:包含一整套单元测试,涵盖了各种可能的函数使用方式。
通常,最初只需要对函数的重要行为编写测试即可,等项目被广泛使用时才考虑全覆盖。
接下来就开始介绍如何采用 unittest 对代码进行测试。
首先是需要导入 unittest 模块,然后创建一个继承 unittest.TestCase 的类,并编写一系列类方法对函数的不同行为进行测试,如下代码所示:
import unittest
class NamesTestCase(unittest.TestCase):
'''
测试生成名字函数的类
'''
def test_first_last_name(self):
formatted_name = get_formatted_name('kobe', 'bryant')
self.assertEqual(formatted_name, 'Kobe Bryant')
unittest.main()
输出结果如下,显示运行的测试样例是 1 个,耗时是 0.001s。
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
上述是给了一个可以通过的例子,而如果测试不通过,输出是怎样的呢,如下所示:
# 添加中间名
def get_formatted_name(first, middel, last):
full_name = first + ' ' + middle + ' ' + last
return full_name.title()
class NamesTestCase(unittest.TestCase):
'''
测试生成名字函数的类
'''
# 不能通过的例子
def test_first_name(self):
formatted_name = get_formatted_name('kobe', 'bryant')
self.assertEqual(formatted_name, 'Kobe Bryant')
unittest.main()
输出结果如下,这里会打印错误发生的地方和错误原因:
E
======================================================================
ERROR: test_first_last_middle_name (__main__.NamesTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "E:/Python_Notes/Practise/unittest_practise.py", line 39, in test_first_last_middle_name
formatted_name = get_formatted_name('kobe', 'bryant')
TypeError: get_formatted_name() missing 1 required positional argument: 'middle'
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (errors=1)
复制代码
很明显是因为缺少 middle
参数,如果希望通过测试,可以将原函数进行如下修改:
def get_formatted_name(first, last, middle=''):
'''
接收姓和名然后返回完整的姓名
:param first:
:param last:
:return:
'''
if middle:
full_name = first + ' ' + middle + ' ' + last
else:
full_name = first + ' ' + last
return full_name.title()
复制代码
然后添加新的测试方法,继续运行,就可以测试通过。
def test_first_last_middle_name(self):
formatted_name = get_formatted_name('kobe', 'bryant', 'snake')
self.assertEqual(formatted_name, 'Kobe Snake Bryant')
测试类
上一小节介绍了给函数写测试的代码,接下来介绍如何编写针对类的测试。
断言方法
在 unitest.TestCase
类中提供了很多断言方法,上一小节就采用了 assertEqual
这一个判断给定两个参数是否相等的断言方法,下面给出常用的 6 个断言方法:
方法 | 用途 |
---|---|
assertEqual(a, b) | 核实 a == b |
assertNotEqual(a, b) | 核实 a != b |
assertTrue(x) | 核实 x 是 True |
assertFalse(x) | 核实 x 是 False |
assertIn(item, list) | 核实 item 在 list 中 |
assertNotIn(item, list) | 核实 item 不在 list 中 |
这些方法都只能在继承了 unittest.TestCase
的类中使用这些方法。
编写针对类的测试
首先,编写用于进行测试的类,代码如下所示,这是一个用于管理匿名调查问卷答案的类:
class AnonymousSurvey():
'''
收集匿名调查问卷的答案
'''
def __init__(self, question):
'''
:param question:
'''
self.question = question
self.responses = []
def show_question(self):
'''
显示问卷
:return:
'''
print(self.question)
def store_response(self, new_response):
'''
存储单份调查问卷
:param new_response:
:return:
'''
self.responses.append(new_response)
def show_results(self):
'''
显示所有答卷
:return:
'''
print('Survey results:')
for response in self.responses:
print('- ' + response)
复制代码
这个类包含三个方法,分别是显示问题、存储单份问卷以及展示所有调查问卷,下面是一个使用例子:
def use_anonymous_survey():
question = "世上最好的语言是?"
language_survey = AnonymousSurvey(question)
# 显示问题
language_survey.show_question()
# 添加问卷
language_survey.store_response('php')
language_survey.store_response('python')
language_survey.store_response('c++')
language_survey.store_response('java')
language_survey.store_response('go')
# 展示所有问卷
language_survey.show_results()
if __name__ == '__main__':
use_anonymous_survey()
复制代码
输出结果如下:
世上最好的语言是?
Survey results:
- php
- python
- c++
- java
- go
然后就开始编写对该类的测试代码,同样创建一个类,继承 unittest.TestCase
,然后类方法进行测试,代码如下所示:
import unittest
class TestAnonmyousSurvey(unittest.TestCase):
def test_store_single_response(self):
'''
测试保存单份问卷的方法
:return:
'''
question = "世上最好的语言是?"
language_survey = AnonymousSurvey(question)
language_survey.store_response('php')
self.assertIn('php', language_survey.responses)
unittest.main()
最后,在 unittest.TestCase
中其实包含一个方法 setUp()
,它的作用类似类的初始化方法 __init()__
,它会在各种以 test_
开头的方法运行前先运行,所以可以在这个方法里创建对象,避免在每个测试方法都需要创建一遍,所以上述代码可以修改为:
class TestAnonmyousSurvey(unittest.TestCase):
def setUp(self):
'''
创建一个调查对象和一组答案
:return:
'''
question = "世上最好的语言是?"
self.language_survey = AnonymousSurvey(question)
self.responses = ['c++', 'php', 'python']
def test_store_single_response(self):
'''
测试保存单份问卷的方法
:return:
'''
self.language_survey.store_response(self.responses[1])
self.assertIn('php', self.language_survey.responses)
def test_store_three_response(self):
for response in self.responses:
self.language_survey.store_response(response)
for response in self.responses:
self.assertIn(response, self.language_survey.responses)
运行后,输出结果如下:
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
注意,这里运行成功,打印一个句号,因为是运行两个测试方法成功,所以打印了两个句号;如果运行出错,打印一个 E
;测试导致断言失败,打印一个 F
。
四、总结
z此时的你再回过头来看看,还会认为登录这个百试不爽的功能就设计十几条甚至几十条测试用例了吗?显然不是那么简单,需要在熟悉需求基础上,进行拆分细化,将常规的思考、经验的积累、理论的支撑结合起来使用,最终才能转化为测试待验证的结果。
感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!有需要的小伙伴可以点击下方小卡片领取