接口测试 unittest实用教程

Posted 墨迹测试

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了接口测试 unittest实用教程相关的知识,希望对你有一定的参考价值。

备注: 本文档针对 接口学习入门人群; ,中级 以及高级测试本篇文档请略过 ; 所有的实例数据来自于聚合数据平台 http://www.haoservice.com/apilist/

requests复习回顾

首先查看 request文件源码:

 
   
   
 
  1. """Constructs and sends a :class:`Request <Request>`.

  2. :param method: method for the new :class:`Request` object.

  3. :param url: URL for the new :class:`Request` object.

  4. :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`.

  5. :param data: (optional) Dictionary or list of tuples ``[(key, value)]`` (will be form-encoded), bytes, or file-like object to send in the body of the :class:`Request`.

  6. :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.

  7. :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.

  8. :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.

  9. :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload.

  10.    ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')``

  11.    or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string

  12.    defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers

  13.    to add for the file.

  14. :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.

  15. :param timeout: (optional) How many seconds to wait for the server to send data

  16.    before giving up, as a float, or a :ref:`(connect timeout, read

  17.    timeout) <timeouts>` tuple.

  18. :type timeout: float or tuple

  19. :param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``.

  20. :type allow_redirects: bool

  21. :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.

  22. :param verify: (optional) Either a boolean, in which case it controls whether we verify

  23.        the server's TLS certificate, or a string, in which case it must be a path

  24.        to a CA bundle to use. Defaults to ``True``.

  25. :param stream: (optional) if ``False``, the response content will be immediately downloaded.

  26. :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.

  27. :return: :class:`Response <Response>` object

  28. :rtype: requests.Response

  29. Usage::

  30.  >>> import requests

  31.  >>> req = requests.request('GET', 'http://httpbin.org/get')

  32.  <Response [200]>

  33. """

以下,对其中主要方法以及参数进行总结:

Requests.request(“请求方法的名字”,”URL”,可选参数)

1.params=字典 :

  • { “id”:”1”,”name”:”张三”}

  • Python中的格式就字典 dict

  • javascript 中叫 json

Params是网址中的参数

2.data = Text 字符串:
data 有以下两种方式表述:

  • "Username = xxx&password=xxxpas" 示例:

 
   
   
 
  1. response = requests.request("post" ,"http://localhost/index.php?m=user&c=public&a=login",data= "url_forward=&username=zhangsan&password=zhangsan")  

  • [("Username"," xxx"),("password","xxxpas")] 示例:

 
   
   
 
  1. data = [("url_forward",""),("username","zhangsan"),("password","zhangsan")]  

  2. response = requests.request("post" ,"http://localhost/index.php?m=user&c=public&a=login",data= data)

 
   
   
 

data是请求实体中的参数 ,请求实体类型 application/x-www-form-urlencoded

3.json=json

{"username":"xxx","password":"xxxpas"}

请求实体类型为 application/json ,通过请求实体发送的

4.headers
5.cookies 6.file
7.auth 认证
通过信息头发送 ;
8.timeout 超时
9.请求方法:类似 ;

 
   
   
 
  1. Request.get(“URL”,可选参数)

  2. Request.post(“URL”,可选参数)

  3. Request.delete(“URL”,可选参数)

  4. Request.put(“URL”,可选参数)

unittest

unittest是一个单元测试框架 ,类似于 java语言中的testng 和junit

作用: 用来组织和执行测试用例 ; 提供了常用的断言 ; 生成了比较丰富的日志信息(测试用例的数量, 测试结果执行的状态,以及测试执行的时间 ,错误用例的报错信息 …) ;提供了很多可扩展的东西(数据驱动测试是在unittest之上 ,生成 测试报告也需要在unittest基础之上,) ;

文本不过多展开讲解, 基本每行代码都进行了注释 ;

一、Pyhon工作原理—— 核心概念:test case, testsuite, TestLoder,TextTestRunner,TextTestResult, test fixture

TestCase(测试用例): 所有测试用例的基类,它是软件 测试中最基本的组成单元。

一个test case就是一个测试用例,是一个完整的测试流程,包括测试前环境的搭建setUp,执行测试代码(run),以及测试后环境的还原(tearDown)。测试用例是一个完整的测试单元,可以对某一问题进行验证。

TestSuite(测试套件):多个测试用例test case集合就是TestSuite,TestSuite可以嵌套TestSuite

TestLoder:是用来加载 TestCase到TestSuite中,其中有几个loadTestsFrom_()方法,就是从各个地方寻找TestCase,创建他们的实例,然后add到TestSuite中,再返回一个TestSuite实例

TextTestRunner:是来执行测试用例的,其中的run(test)会执行TestSuite/TestCase中的run(result)方法。

TextTestResult:测试结果会保存到TextTestResult实例中,包括运行了多少用例,成功与失败多少等信息

TestFixture:又叫测试脚手,测试代码的运行环境,指测试准备前和执行后要做的工作,包括setUp和tearDown方法

二、测试流程:

1.写好TestCase:一个class继承unittest.TestCase,就是一个测试测试用例,其中有多个以test开头的方法,那么 每一个这样的,在load的时候会生成一个TestCase实例。如果一个class中有四个test开头的方法,最后load到suite中时则有四个测试用例

2.由TestLoder加载TestCase到TestSuite

3.然后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中。

说明:

a:通过命令行或者unittest.main()执行时,main会调用TextTestRunner中的run来执行,或者可以直接通过TextTestRunner来执行用例

b:Runner执行时,默认将结果输出到控制台,我们可以设置其输出到文件,在文件中查看 结果,也可以通过htmlTestRunner将结果输出到HTML)

三、详细示例:

快速入门实例:

新建unittestDemo.py文件 ;

 
   
   
 
  1. # 1.导入 unittest, unittest是python内置的代码库, 不需要单独下载 ;

  2. import  unittest

  3. # 2.继承unittest代码库中的 TestCase测试用例类 ;

  4. # 文件名一般首字母小写,类名首字母大写 , 文件名和类名一般就第一个字母不一样 ,

  5. # 在java中 继承使用extends关键字 ,python中使用 小括号()

  6. class UniittestDemo(unittest.TestCase):

  7.    chrome = "谷歌浏览器"

  8.    # 3. 重写父类中的 setUp 和 tearDown 方法

  9.    # 在 Python中 ,方法有一个关键字叫做 :def

  10.    # self是 方法的第一个默认参数,self类似于 java中的 this关键字 ;

  11.    # self 指的是当前类, 要想调用类中的属性或者方法, 前面需要加上self

  12.    # setUp是建立的意思,类似于testng中的 beforeMethod(),负责测试用例之前的准备工作 ;

  13.    def setUp(self):

  14.        print(1)

  15.        print(self.chrome)

  16.    # tearDown 是拆除销毁的意思, 类似于testng中的 afterMethod() ,负责测试用例执行后的恢复工作;

  17.    def tearDown(self):

  18.        print(2)

  19.    # 4. 编写 测试用例类

  20.    # 在 unittest中, 测试用例方法, 必须以test字符串开头, 类似于testng中,每个测试方法之上必须加@Test注解 ;

  21.    def test_login(self):

  22.        print(3)

  23.    # 默认打印 1 3 2 ,

  24.    # Python中对格式的要求比 java严格,遇到冒号就必须缩进 4个空格 为准

  25.    def test_register(self):

  26.        print(4)

  27.    # 每次执行测试用例 ,都会重新执行一遍setUp(), tearDown()方法 ;

  28.    # 如果光标在某个 方法内部运行程序, 那么只会运行该方法,

  29.    # 一般在测试用例类外面,我们写一个 main关键字方法 , 类似于java中 public static void mian(String[] args){}

  30. # __name__ == '__main__'类似于主函数 ,在这段方法中写的代码,将不会被其他文件调用 ;(常用来做调试用)

  31. if __name__ == '__main__':

  32.    # 默认执行当前文件中的测试用例方法 ;

  33.    # unittest.main(UniittestDemo)

  34.    unittest.main()

Output:

新建 mainDemo.py文件

 
   
   
 
  1. # 一般方法 ,普通方法只有被调用才能执行

  2. def read():

  3.    print(1)

  4. read()

  5. if __name__ == '__main__':

  6.    read()

  7. # 这两种写法有什么区别 ??

  8. # main()下面的read方法只能在当前文件执行;

  9. # main上面的调用read方法 ,只要其他文件引用了这文件就会被执行;

  10. # 所以如果想要在类外部直接调用某个方法, 一般都是 if __name__ == '__main__': 方法中执行 ;


新建 callMainDemo.py文件, 验证 if__name__=='__main__':

 
   
   
 
  1. #  导包快捷键 ,光标点击红色波浪线 ~ Alt+Enter

  2. from mainDemo import read

  3. read()

断言

所有的测试用例都必须包含断言 ,一个测试用例中,可以包含多个断言 ; 断言是由unittest单元自动化测试框架提供的 ;

新建 answerRebotTest.py文件 ;

 
   
   
 
  1. import unittest

  2. import requests

  3. class AnswerRebotTest(unittest.TestCase):

  4.    def setUp(self):

  5.        self.url = "http://apis.haoservice.com/efficient/robot"

  6.    def tearDown(self):

  7.        print(self.result)

  8.    def test_answer_rebot(self):

  9.        parameters = {"info": "你好美男子", "address": "", "key": "3b1cf1120c2347d4b2c48149abb3e7b5"}

  10.        response = requests.request("get",self.url ,params = parameters)

  11.        self.result =response.json()

  12.        # 第一个参数 期望结果 ,第二个参数 实际结果, 第三个参数 : 断言不通过时 ,提示信息

  13.        self.assertEqual('成功',self.result['reason'])

  14.        self.assertEqual(0,self.result['error_code'] )

  15.        self.assertEqual(100000,self.result['result']['code'])

  16.        # 编码代码时 ,要保持所有的测试用例都能 pass , 只有当回归测试或者数据驱动测试的时候,才有可能发现缺陷 ;

  17. if __name__ == '__main__':

  18.    unittest.main()

数据驱动测试

读取csv文件的思路:

1.准备 csv文件                                                                                                        2.导入csv 代码库
3.指定需要读取的csv文件的路径 ;
4.打开 csv文件 ,
5.通过csv代码库提供的方法 ,读取csv文件中的内容
6.打印csv文件中的内容

文件示例如下:

数据文件 : answerRebotTestData.csv

接口测试 unittest实用教程

新建 csvFileManager.py文件 ;

 
   
   
 
  1. # 1.   准备 csv文件

  2. # 2.   导入csv 代码库

  3. import  csv

  4. # 3.   指定需要读取的csv文件的路径 ;

  5. # 路径中的斜杠处理方式 有三种:

  6. # 1.用双反斜线代替反斜线 2.在整个字符串前加 字母r  ,用 r表示该字符串不存在转移字符 ;3.将反斜线改为正斜线

  7. # 推荐 3, 使用正斜线可以跨平台

  8. path  = r"D:\pyworkspace\apitest\data\answerRebotTestData.csv"

  9. # 4.   打开 csv文件 ,

  10. file = open(path,'r')

  11. # 5.   通过csv代码库提供的方法 ,读取csv文件中的内容

  12. content = csv.reader(file)

  13. # 6.   打印csv文件中的内容

  14. print(content)

  15. for row in content:

  16.    print( row)

  17. #  测试用例类至少要调用这段代码, 才能得到csv文件中的数据

  18. #  必须要把这段代码封装成一个方法,

  19. #  详情见 csvFileManage2.py

测试用例如何接收读取的测试数据

1.导入ddt 即 data driver test ,不是内置的代码库需要单独下载
cmd : pip install ddt
2.准备好读取csv文件的方法
该方法需要有一个返回值,返回csv文件中的数据,以二维列表的方式显示所有数据

新建 csvFileManager2.py文件:

 
   
   
 
  1. import csv

  2. def readCsv(filename):

  3.    path = 'D:/pyworkspace/apitest/data/' +filename +'.csv'

  4.    file = open(path,"r")

  5.    content = csv.reader(file)

  6.    testdata = []   #申明一个空的列表

  7.    i = 0

  8.    for row in content:

  9.        if i ==0:

  10.            print("当前行为表头")

  11.        else:

  12.            testdata.append(row)

  13.        i= i+1

  14.    return testdata

  15. if __name__ == '__main__':

  16.    testdata = readCsv("answerRebotTestData")

  17.    print(testdata)

3.在测试用例类上添加装饰器: @ddt.ddt
Python中的装饰器类似于java中的注解;                                                                          
@ddt.ddt这个装饰器的作用 ,就是标志这个类采用ddt的方式提供测试数据                   
4.申明一个成员变量 ;
以 csvFileManage.readCsv(文件名) 的返回值作为变量的值
5.在test方法上添加装饰器 : @ddt.data(*成员变量的变量)
6.修改方法的参数列表,增加一个列表类型参数
7.修改方法体 ,用变量名称替代原来的字符串常量

添加ddt后,修改后的answerRebotTest.py文件如下: 

 
   
   
 
  1. import unittest

  2. # 1.导入ddt 代码库

  3. import ddt

  4. import requests

  5. # 2.为类添加装饰器

  6. import csvFileManage2

  7. @ddt.ddt

  8. class AnswerRebotTest(unittest.TestCase):

  9.    # 3.申明一个成员变量,读取csv文件中的数据

  10.    test_data = csvFileManage2.readCsv("answerRebotTestData")

  11.    def setUp(self):

  12.        self.url = "http://apis.haoservice.com/efficient/robot"

  13.    def tearDown(self):

  14.        print(self.result)

  15.    # 4.为测试方法添加装饰器 @ddt.data(*variable)

  16.    # 在python中 ,给列表前面加上* 号, 表示把列表拆分为多个元素 ;

  17.    #  example: list=[a,b,c]

  18.    #  *list = a,b,c

  19.    #  这样就把一个list类型的元素, 拆分成了三个不同变量 ;

  20.    #  list中有几个元素, 就会拆分为几个变量 ;

  21.    @ddt.data(*test_data)

  22.    # 5.在方法的参数列表中添加一个形参 ,这个形参代表一组测试数据 ,就是excel中的每一行 ;

  23.    def test_answer_rebot(self,row ):

  24.        # 6.用row[n]代替原来写死的字符串常量

  25.        parameters = {"info": row[1], "address": row[2], "key": row[0]}

  26.        response = requests.request("get",self.url ,params = parameters)

  27.        self.result =response.json()

  28.        # 第一个参数 期望结果 ,第二个参数 实际结果, 第三个参数 : 断言不通过时 ,提示信息

  29.        self.assertEqual(row[3],self.result['reason'])

  30.        # row[4] 默认从csv文件读取出来的是 text ,需要 int()方法进行转换 ;

  31.        self.assertEqual(int(row[4]),self.result['error_code'] )

  32.        # self.assertEqual(100000,self.result['result']['code'])

  33.        # 编码代码时 ,要保持所有的测试用例都能 pass , 只有当回归测试或者数据驱动测试的时候,才有可能发现缺陷 ;

  34. if __name__ == '__main__':

  35.    unittest.main()

批量执行测试用例

1.找出所有测试用例 :

test_suite  = unittest.defaultTestLoader.discover(目录,文件名规则)

2.执行找出的测试用例 :

unittest.TextTestRunner().run(test_suite)

将要测试的py文件统一放在 test_case目录 ;如图:

接口测试 unittest实用教程

新建一个runallcases.py文件:

 
   
   
 
  1. import unittest

  2. if __name__ == '__main__':

  3.    # 1.找出所有的 unittest测试用例

  4.    # defaultTestLoader 默认的测试用例加载器

  5.    # 通过discover方法,设置规则 ,找出所有符合规则的测试用例 ;

  6.    #.表示当前路径, run_all_case.py在项目的根节点位置 ;

  7.    test_suite = unittest.defaultTestLoader.discover('./case_test', pattern='*.py', top_level_dir=None)

  8.    # 执行找到的所有测试用例 ;

  9.    # TextTestRunner()文本格式的测试用例器 ;用来执行测试用例的 ,

  10.    unittest.TextTestRunner().run(test_suite)

生成测试报告

1.导入HtmlTestRunner.py文件 (建议单独放在一个包内)
2.使用这个文件中的HtmlTestRunner类 ,代替unittest中的 TextTestRunner类,执行测试

通过类名, 一个是生成html格式的测试报告的测试用例执行器 , 另一个是生成文本日志格式 测试报告测试用例(只会打印在控制台) ;

3.现在生成一个新的文件,那么需要指定测试报告的保存路径 ;

在项目中创建一个report的文件夹

如图查看: 我在项目根目录下新建了package目录,将HTMLTestRunner.py文件拷贝进去 ,新建report目录,用来存放生成的测试报告 ;

接口测试 unittest实用教程

使用 HtmlTestRunner.py如何生成测试报告呢? 见以下代码:

接口测试 unittest实用教程

使用 HtmlTestRunner生成测试报告, runallcase.py文件内容完整如下:

 
   
   
 
  1. import unittest

  2. import sys

  3. from package.HTMLTestRunner import HTMLTestRunner

  4. if __name__ == '__main__':

  5.    # 1.找出所有的 unittest测试用例

  6.    # defaultTestLoader 默认的测试用例加载器

  7.    # 通过discover方法,设置规则 ,找出所有符合规则的测试用例 ;

  8.    #.表示当前路径, run_all_case.py在项目的根节点位置 ;

  9.    test_suite = unittest.defaultTestLoader.discover('./case_test', pattern='*.py', top_level_dir=None)

  10.    #

  11.    # 2a .执行找到的所有测试用例 ;

  12.    # TextTestRunner()文本格式的测试用例器 ;用来执行测试用例的 ,

  13.    # unittest.TextTestRunner().run(test_suite)

  14.    # 2b .用 HtmlTestRunner代替TextTestRunner

  15.    # stream 代表流的意思 , 这里要求填入一个2进制的文件流

  16.    # 3 .为生成的Html测试报告指定路径

  17.    path = "./report/"

  18.    file_path = path + "ApiTestReport.html"

  19.    file = open(file_path , "wb")

  20.    HTMLTestRunner(stream=file, verbosity=1,title="ApiTest接口自动化测试报告",description="学会使用unittest测试框架 ,soeasy", tester = "Young").run(test_suite)

右键 run 后 ,查看多了 ApiTestReport.html文件:

接口测试 unittest实用教程

使用chrome浏览器进行查看 ;

接口测试 unittest实用教程

查看通过的详情 截图:  

接口测试 unittest实用教程

查看通过详情信息:  

接口测试 unittest实用教程

至此 .本篇完结 ;


拂晓时分


                       我伫立在阒无一人的街角


我熬过了夜晚


——博尔赫斯

一切经得起再度阅读的语言,

一定值得再度思索

——梭罗

接口测试 unittest实用教程

你穿过世事朝我走来 迈出的每一步都留下了一座空城 这时,一支从来世射出的毒箭命定了我 唯一的退路 --仓央嘉措

我这一生的种种 都是万事之来 往往顺其自然 当不得已处 实不愿拂逆旁人之意 宁可舍己从人  

                                                                                              by  Young


心念一转,万念皆转;心路一通,万路皆通。

以上是关于接口测试 unittest实用教程的主要内容,如果未能解决你的问题,请参考以下文章

测试教程网.unittest教程.6. 命令行接口

python+request+HTMLTestRunner+unittest接口自动化测试框架

unittest介绍

Python接口测试之unittest框架

Python接口测试之unittest

测试教程网.unittest教程.8. 断言异常