单元测试之setUp,全局变量,反射和数据参数化

2020-12-02 16:44:53 浏览数 (1)

文章总览图

1.后面的用例需要用到第一条用例的返回结果里的某些值,怎么去处理这种依赖关系?

方法一: 第1条用例写在setUp里面,每次请求的时候,在setUp里面重新请求第一条用例。 缺点就是关联性比较强,一步错,步步错。

方法二: 全局变量 缺点就是关联性比较强,一步错,步步错。

外面的是全局变量,函数里面的是局部变量。 如果要修改全局变量的值,怎么去改? 先global声明全局变量,才能去修改局部变量的值。

方法三: 反射---不强调 这种方法更简单。

setattr(GetData,"Cookie","小白")

代码语言:javascript复制
            #  类名     属性名   新值

可以直接把类里面的属性值做修改,进行更新。缺点就是关联性比较强,一步错,步步错。

数据参数化: 可以解决用例的关联性强,一步错,步步错的问题。

Http请求:创建实例.方法(参数)

下面操作需要先在Python里面安装requests库,pip install requests

2.代码如下

单元测试思路:第1个地址是登录的接口地址,第2个地址是登录进去后进行充值的接口地址。两个接口地址是同一个网站的。

由于清菡没有找到这样的接口,所以用的别的接口地址,学的是思路。

先创建一个http_request.py文件,调用requests库,对get和post请求成功封装。

代码语言:javascript复制
#来自文件http_request.py

import requests
class HttpRequest:
    '''利用request封装get请求和post请求'''

    def http_request(self,url,data,method,cookie=None):
        '''url:请求的地址 http://xxx:port
               param:传递的参数  非必填参数  字典的格式传递参数
               method:请求方式支持get以及post  字符串形式的参数
               cookie:请求的时候传递的cookie值'''
        if method.lower()=='get':
            res = requests.get(url, data, cookies=cookie)
        else:
            res=requests.post(url,data,cookies=cookie)#响应结果的消息实体 http response包含响应头,响应状态码,响应正文,Cookie
        return res#返回一个消息实体
if  __name__ =='__main__':
    url = 'http://v.juhe.cn/xhzd/query'
    data = {"key": "e0dd844ff0669814b529da934a094a83", "word": '聚'}
    res=HttpRequest().http_request(url,data,'post')
    print("登录结果是:", res.json())

#充值
    recharge_url='http://v.juhe.cn/xhzd/query'
    recharge_data={"key":"e0dd844ff0669814b529da934a094a83","word":'聚'}
    recharges_res=HttpRequest().http_request(recharge_url,recharge_data,'get',res.cookies)
    print("充值结果是:",recharges_res.json())

方法一:setUp

写在setUp里面,每次请求的时候在setUp里面重新请求第一条用例。

代码语言:javascript复制
#来自文件test_http.py

#输入错误的密码和充值为负数没有加断言,所以结果全部通过。
import unittest
from test_demo.http_request import HttpRequest

class TestHttp(unittest.TestCase):
    def setUp(self):
        #登录
        self.login_url='http://v.juhe.cn/xhzd/query'
        self.login_data={"key": "e0dd844ff0669814b529da934a094a83", "word": '聚'}
        #充值的URL
        self.recharge_url= 'http://v.juhe.cn/xhzd/query'
        #获取登录后的cookies
        self.cookies=HttpRequest().http_request(self.login_url,self.login_data,'get').cookies
        print("setUp函数里面登录后产生的cookies是:{}".format(self.cookies))

    def test_login_normal(self):#正常登录
        data={"key": "e0dd844ff0669814b529da934a094a83", "word": '聚'}
        res=HttpRequest().http_request(self.login_url,data,'get')
        try:
            self.assertEqual('返回成功',res.json()['reason'])
        except AssertionError as e:
            print("test_login_normal's error is{}".format(e))
            raise e
        print(res.json())

    def test_login_wrong_pwd(self):#输入错误的密码
        data={"key": "e0dd844ff0669814b529da934a094a83", "word": ''}
        res=HttpRequest().http_request(self.login_url,data,'get')
        print(res.json())

    def test_recharge_normal(self):#正常充值
        recharge_data = {"key": "e0dd844ff0669814b529da934a094a83", "word": '聚'}
        res=HttpRequest().http_request(self.recharge_url,recharge_data,'post',self.cookies)#加了一个cookies
        try:
            self.assertEqual('返回成功', res.json()['reason'])
        except AssertionError as e:
            print("test_recharge_normal's error is{}".format(e))
            raise e
        print(res.json())

    def test_recharge_negative(self):#充值为负数
        recharge_data = {"key": "e0dd844ff0669814b529da934a094a83", "word": ''}
        res=HttpRequest().http_request(self.recharge_url,recharge_data,'post',self.cookies)#加了一个cookies
        print(res.json())


    def tearDown(self):
        pass


写断言的时候,需要把响应结果里面的值填写进去。

代码语言:javascript复制
#来自文件test_suite.py

#用的不是登录-充值的接口,测试的时候最好找到能登录进去并进行充值的接口。

import unittest
import HTMLTestRunner
from test_demo import test_http#模块名
suite=unittest.TestSuite()
#通过loader方式来加载用例,其它的方式也可以尝试。
loader=unittest.TestLoader()
suite.addTest(loader.loadTestsFromModule(test_http))


#执行
with open("test_summer.html",'wb')as file:
    runner=HTMLTestRunner.HTMLTestRunner(stream=file, verbosity=2,title="单元测试",description=None,tester="清菡")
    runner.run(suite)

文件夹下已创建文件http_request.py,文件test_http.py和文件test_suite.py,运行文件test_suite.py。

输出结果如下:

输入错误的密码和充值为负数没有加断言,所以结果全部通过。

输入错误的密码和充值为负数的用例中增加了断言

代码语言:javascript复制
#来自文件test_http_Assert.py

import unittest
from test_demo.http_request import HttpRequest

class TestHttp(unittest.TestCase):
    def setUp(self):
        #登录
        self.login_url='http://v.juhe.cn/laohuangli/d'
        self.login_data={"key": "abf91475fc19f66c2f1fe567edd75257", "date": '2014-09-09'}
        #充值的URL
        self.recharge_url= 'http://v.juhe.cn/laohuangli/d'
        #获取登录后的cookies
        self.cookies=HttpRequest().http_request(self.login_url,self.login_data,'get').cookies
        print("setUp函数里面登录后产生的cookies是:{}".format(self.cookies))

    def test_login_normal(self):#正常登录
        data={"key": "abf91475fc19f66c2f1fe567edd75257", "date": '2014-09-09'}
        res=HttpRequest().http_request(self.login_url,data,'get')
        try:
            self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
        except AssertionError as e:
            print("test_login_normal's error is{}".format(e))
            raise e
        print(res.json())

    def test_login_wrong_pwd(self):#输入错误的密码
        data={"key": "abf91475fc19f66c2f1fe567edd75257", "date": ''}
        res=HttpRequest().http_request(self.login_url,data,'get')
        try:
            self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
        except AssertionError as e:
            print("test_login_wrong_pwd's error is{}".format(e))
            raise e
        print(res.json())

    def test_recharge_normal(self):#正常充值
        recharge_data = {"key": "abf91475fc19f66c2f1fe567edd75257", "date": '2014-09-09'}
        res=HttpRequest().http_request(self.recharge_url,recharge_data,'post',self.cookies)#加了一个cookies
        try:
            self.assertEqual('超过每日可允许请求次数!', res.json()['reason'])
        except AssertionError as e:
            print("test_recharge_normal's error is{}".format(e))
            raise e
        print(res.json())

    def test_recharge_negative(self):#充值为负数
        recharge_data ={"key": "abf91475fc19f66c2f1fe567edd75257", "date": ''}
        res=HttpRequest().http_request(self.recharge_url,recharge_data,'post',self.cookies)#加了一个cookies
        try:
            self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
                             #预期结果
        except AssertionError as e:
            print("test_recharge_negative's error is{}".format(e))
            raise e#注意:实际结果与预期结果不符合的情况下没加raise e 通过,加了raise e 用例才抛出错误。
    #如果实际结果和预期结果是一致的,加raise e 和不加raise e,用例都是通过的。
        print(res.json())


    def tearDown(self):
        pass

前1次代码,因为输入错误的密码和充值为负数没有加断言,所以结果全部通过。可以在上次的结果中取这块的值放进断言中,为错误的密码和充值为负数的用例中增加断言。

图片中仅供参考,根据实际的接口情况,取值。

代码语言:javascript复制
#来自文件test_suite.py

#此接口不是登录-充值的接口

import unittest
import HTMLTestRunner
from test_demo import test_http_Assert#模块名
suite=unittest.TestSuite()
#通过loader方式来加载用例,其它的方式也可以尝试。
loader=unittest.TestLoader()
suite.addTest(loader.loadTestsFromModule(test_http_Assert))


#执行
with open("test_summer.html",'wb')as file:
    runner=HTMLTestRunner.HTMLTestRunner(stream=file, verbosity=2,title="单元测试",description=None,tester="清菡")
    runner.run(suite)

文件夹下已创建文件http_request.py,文件test_http_Assert.py和文件test_suite.py,运行文件test_suite.py。

输出结果如下:

注意:实际结果与预期结果不符合的情况下,没加raise e 通过,加了raise e 用例才抛出错误。如果实际结果和预期结果是一致的,加raise e和不加raise e,用例都是通过的。

实际结果与预期结果不符合的情况下,加了raise e 用例抛出错误。

方法二:全局变量

代码语言:javascript复制
#文件来自quanjubianliang.py

import unittest
from test_demo.http_request import HttpRequest
COOKIE=None#全局变量

class TestHttp(unittest.TestCase):
    def setUp(self):
        #登录
        self.login_url='http://v.juhe.cn/xhzd/query'
        #充值的URL
        self.recharge_url= 'http://v.juhe.cn/xhzd/query'
        #获取登录后的cookies
        # self.cookies=Httprequest().http_request(self.login_url,self.login_data,'get').cookies
        # print("setUp函数里面登录后产生的cookies是:{}".format(self.cookies))

    def test_login_normal(self):#正常登录
        global COOKIE#声明全局变量
        data={"key":"e0dd844ff0669814b529da934a094a83","word":'聚'}
        res=HttpRequest().http_request(self.login_url,data,'get')
    #if条件语句,后面为空就是False,不为空就是True。res.cookies不为空就是有cookie,有cookie的时候再去做替换。
        if res.cookies:#如果cookie有的话,就更新COOKIE
            COOKIE=res.cookies
        try:
            self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
        except AssertionError as e:
            print("test_login_normal's error is{}".format(e))
            raise e
        print(res.json())

    def test_login_wrong_pwd(self):#输入错误的密码登录
        data={"key":"e0dd844ff0669814b529da934a094a83","word":''}
        res=HttpRequest().http_request(self.login_url,data,'get')
        try:
            self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
        except AssertionError as e:
            print("test_login_normal's error is{}".format(e))
            raise e
        print(res.json())

    def test_recharge_normal(self):#登录后正常充值
        global COOKIE#加了global才能修改它的值,局部变量要修改全局变量的值,就要声明它是个全局变量。
        recharge_data = data={"key":"e0dd844ff0669814b529da934a094a83","word":'聚'}
        res=HttpRequest().http_request(self.recharge_url,recharge_data,'post',COOKIE)#加了一个全局变量cookie
        try:
            self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
        except AssertionError as e:
            print("test_recharge_normal's error is{}".format(e))
            raise e
        print(res.json())

    def test_recharge_negative(self):#登录后充值为负数
        global COOKIE
        recharge_data =data={"key":"e0dd844ff0669814b529da934a094a83","word":''}
        res=HttpRequest().http_request(self.recharge_url,recharge_data,'post',COOKIE)#加了一个全局变量cookie
        try:
            self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
        except AssertionError as e:
            print("test_recharge_negative's error is{}".format(e))
            raise e#注意:实际结果与预期结果不符合的情况下没加raise e 通过,加了raise e 用例才抛出错误。
    #如果实际结果和预期结果是一致的,加raise e 和不加raise e,用例都是通过的。
        print(res.json())


    def tearDown(self):
        pass
代码语言:javascript复制
#来自文件test_suite.py
#不是登录-充值的接口

import unittest
import HTMLTestRunner
from test_demo import quanjubianliang#模块名
suite=unittest.TestSuite()
#通过loader方式来加载用例,其它的方式也可以尝试。
loader=unittest.TestLoader()
suite.addTest(loader.loadTestsFromModule(quanjubianliang))


#执行
with open("test_summer.html",'wb')as file:
    runner=HTMLTestRunner.HTMLTestRunner(stream=file, verbosity=2,title="单元测试",description=None,tester="清菡")
    runner.run(suite)

文件夹下已创建文件http_request.py,文件quanjubianliang.py和文件test_suite.py,运行文件test_suite.py。

输出结果如下:

方法三:反射

代码语言:javascript复制
#来自文件get_data.py

class GetData:
    Cookie=None#存储cookie,初始值为None
代码语言:javascript复制
#文件来自fanshe.py

import unittest
from test_demo.http_request import HttpRequest
from test_demo.get_data import GetData

class TestHttp(unittest.TestCase):
    def setUp(self):
        #登录
        self.login_url='http://v.juhe.cn/laohuangli/d'
        #充值的URL
        self.recharge_url= 'http://v.juhe.cn/laohuangli/d'

    def test_login_normal(self):#正常登录
        data={"key": "abf91475fc19f66c2f1fe567edd75257", "date": '2014-09-09'}
        res=HttpRequest().http_request(self.login_url,data,'get')
    #if条件语句,后面为空就是False,不为空就是True。res.cookies不为空就是有cookie,有cookie的时候再去做替换。
        if res.cookies:#如果cookie有的话,就更新COOKIE
              setattr(GetData,'Cookie',res.cookies)
        try:
            self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
        except AssertionError as e:
            print("test_login_normal's error is{}".format(e))
            raise e
        print(res.json())

    def test_login_wrong_pwd(self):#输入错误的密码登录
        data={"key": "abf91475fc19f66c2f1fe567edd75257", "date": '2014-09-11'}
        res=HttpRequest().http_request(self.login_url,data,'get')
        try:
            self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
        except AssertionError as e:
            print("test_login_normal's error is{}".format(e))
            raise e
        print(res.json())

    def test_recharge_normal(self):#登录后正常充值
        recharge_data = {"key": "abf91475fc19f66c2f1fe567edd75257", "date": '2014-09-09'}
        res=HttpRequest().http_request(self.recharge_url,recharge_data,'post',getattr(GetData,"Cookie"))
        try:
            self.assertEqual('超过每日可允许请求次数!', res.json()['reason'])
        except AssertionError as e:
            print("test_recharge_normal's error is{}".format(e))
            raise e
        print(res.json())

    def test_recharge_negative(self):#登录后充值为负数
        recharge_data = {"key": "abf91475fc19f66c2f1fe567edd75257", "date": '-2014-09-09'}
        res=HttpRequest().http_request(self.recharge_url,recharge_data,'post',getattr(GetData,"Cookie"))
        try:
            self.assertEqual('超过每日可允许请求次数!',res.json()['reason'])
        except AssertionError as e:
            print("test_recharge_negative's error is{}".format(e))
            raise e
        print(res.json())


    def tearDown(self):
        pass
代码语言:javascript复制
#文件来自test_suite.py
#不是登录-充值的接口

import unittest
import HTMLTestRunner
from test_demo import fanshe#模块名
suite=unittest.TestSuite()
#通过loader方式来加载用例,其它的方式也可以尝试。
loader=unittest.TestLoader()
suite.addTest(loader.loadTestsFromModule(fanshe))


#执行
with open("test_summer.html",'wb')as file:
    runner=HTMLTestRunner.HTMLTestRunner(stream=file, verbosity=2,title="单元测试",description=None,tester="清菡")
    runner.run(suite)

文件夹下已创建文件http_request.py,get_data.py文件,fanshe.py和文件test_suite.py,运行文件test_suite.py。

输出结果如下:

介绍反射的原理

代码语言:javascript复制
#介绍反射的原理
class GetData:
        Cookie=None
        # Cookie='小郭'

if __name__ == '__main__':

    print(GetData.Cookie)
    setattr(GetData,"Cookie","小白")#1 可以直接把类里面的属性值做修改
          #  类名     属性名   新值
    print(hasattr(GetData,"Cookie"))#2 判断是否有这个属性值
    print(getattr(GetData,"Cookie"))#3  attribute 属性 获取这个属性值
    delattr(GetData,"Cookie")#4 把这个属性删掉
    # print(GetData.Cookie)
    print(hasattr(GetData,"Cookie"))#判断是否有这个属性值

直接运行代码就可以。

参数化

地址不一样,测试数据不同,断言的期望结果不同,除了这几个不同,其它的都是高度相似的,80%相似,可以用参数化。

参数化 url data expected

代码语言:javascript复制
#来自文件get_data.py

class GetData:
    Cookie=None#存储cookie,初始值为None
代码语言:javascript复制
#来自文件http_request.py

import requests
class HttpRequest:
    '''利用request封装get请求和post请求'''

    def http_request(self,url,data,method,cookie=None):
        '''url:请求的地址 http://xxx:port
               param:传递的参数  非必填参数  字典的格式传递参数
               method:请求方式支持get以及post  字符串形式的参数
               cookie:请求的时候传递的cookie值'''
        if method.lower()=='get':
            res = requests.get(url, data, cookies=cookie)
        else:
            res=requests.post(url,data,cookies=cookie)#响应结果的消息实体 http response包含响应头,响应状态码,响应正文,Cookie
        return res#返回一个消息实体

if  __name__ =='__main__':
    url = 'http://v.juhe.cn/xhzd/query'
    data = {"key": "e0dd844ff0669814b529da934a094a83", "word": '聚'}
    res=HttpRequest().http_request(url,data,'post')
    print("登录结果是:", res.json())

#充值
    recharge_url='http://v.juhe.cn/xhzd/query'
    recharge_data={"key": "e0dd844ff0669814b529da934a094a83", "word": '聚'}
    recharges_res=HttpRequest().http_request(recharge_url,recharge_data,'get',res.cookies)
    print("充值结果是:",recharges_res.json())
代码语言:javascript复制
#来自文件test_http.py

#开拓思维必学
import unittest
from class_1101.http_request import HttpRequest
from class_1101.get_data import GetData


class TestHttp(unittest.TestCase):
    def setUp(self):
        pass

    # 数据给它参数化,通过初始化传参,实现参数化
    def __init__(self,methodName,url,data,method,expected):#通过初始化函数来传参数
        super(TestHttp,self).__init__(methodName)#父类的方法要保留,用的超继承。
        self.url=url
        self.data=data
        self.method=method
        self.expected=expected

    def test_api(self):#接口用例
            res=HttpRequest().http_request(self.url,self.data,self.method,getattr(GetData,'Cookie'))
            if res.cookies:#如果cookie有的话,就更新COOKIE
                  setattr(GetData,'Cookie',res.cookies)#反射
            try:
                self.assertEqual(self.expected,res.json()['reason'])
            except AssertionError as e:
                print("test_api's error is{}".format(e))
                raise e
            print(res.json())

    def tearDown(self):
        pass
代码语言:javascript复制
#来自文件test_suite.py

#不是登录-充值的接口

import unittest
import HTMLTestRunner
from class_1101.test_http import TestHttp#类名

#列表里面嵌套了字典
test_data=[{"url":'http://v.juhe.cn/xhzd/query',                             #期望值
            "data":{"key": "e0dd844ff0669814b529da934a094a83", "word": '聚'},"expected":'超过每日可允许请求次数!','method':'get'},
           {"url":'http://v.juhe.cn/xhzd/query',
            "data":{"key": "e0dd844ff0669814b529da934a094a83", "word": ''},"expected":'超过每日可允许请求次数!','method':'post'},
           {"url":'http://v.juhe.cn/xhzd/query',
            "data": {"key": "e0dd844ff0669814b529da934a094a83", "word": '聚'},"expected":'超过每日可允许请求次数!','method':'get'},
           {"url":'http://v.juhe.cn/xhzd/query',
            "data" :{"key": "e0dd844ff0669814b529da934a094a83", "word": ''},"expected":'超过每日可允许请求次数!','method':'post'}]
suite=unittest.TestSuite()

#遍历数据
for item in  test_data:#创建实例
    suite.addTest(TestHttp("test_api",item['url'],item['data'],item['method'],item['expected']))
#实例的方式去加载用例url,data,method,expected


#执行
with open("test_summer.html",'wb')as file:
    runner=HTMLTestRunner.HTMLTestRunner(stream=file, verbosity=2,title="单元测试",description=None,tester="清菡")
    runner.run(suite)

文件夹下已创建文件http_request.py,get_data.py文件,test_http.py和文件test_suite.py,运行文件test_suite.py。

输出结果如下:


0 人点赞