学习笔记之软件测试2:基于Python的单元测试方法(Testcase+Pytest)

前言

  • 文章比较详细,建议先收藏
  • 下一步:项目的具体测试
  • 有任何问题,评论区留言

单元测试的目的

单元测试的由来

在软件测试的发展过程中衍生的一种测试方法,能够更高效率、更简洁地实现软件系统的模块化的测试。

单元测试的优势

  • 极大程度上节约测试时间
    复杂的交互场景中自动化地帮助自己测试组件,更快速的定位错误代码位置。
  • 测试本身不仅是发现错误,更能预防错误
    测试能够协助开发以更清晰的思路认识自己的代码问题,只有认识到代码问题才能够让代码优化,带给客户更优质的体验。
  • 能够让代码更加简洁
    测试后的代码,逻辑更加清晰,能够减少代码冗余。

Request模块

Request模块简介

介绍

一、说明

​ Request模块是一个模拟用户在客户端发送各种请求的基于HTTP协议的Python库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P8V9rGXa-1602593196197)(C:\Users\Pine\Desktop\03.png)]

二、作用

  • 软件测试使用:脚本化发送请求并分析返回数据是否异常
  • 爬虫使用:模拟用户脚本化自动采集网络资源

安装

# 切换虚拟环境!!!  安装镜像源为清华园
pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple 

请求方式以及响应

HTTP接口动词说明

在这里插入图片描述

查询参数对应的request模块中的请求方式

查询参数 所有请求方式->requests.get(params={})
请求体 json参数 非get请求方式(post、put、delete)->requests.post(json={})
请求体 form参数 非get请求方式(post、put、delete)->requests.post(data={})
参数传递方式 requests 接收的关键参数名字
请求头参数 所有请求方式->requests.get(headers={})

Request模块使用(Httpbin.org)

httpbin.org说明:之后的测试案例都采用对这个网站进行请求的方案

  1. 作用:测试HTTP的Request请求并返回对应的Response信息,适用于GET、POST各种请求接口
  2. 项目架构:基于Python的Flask框架 开源
  3. Github地址:https://github.com/Runscope/httpbin
  4. 官网:http://httpbin.org/
  • Get 请求

    import requests
    from requests import Request, Session
    
    # 1. 定义URL对象
    # url = 'http://www.meiduo.site:8080/'
    url = 'http://httpbin.org/get'
    # 2. 新建request对象 注意+请求方式
    response = requests.get(url)
    # 3. 检查获取的数据格式以及内容打印到一个文件中
    with open('test1.html', 'w') as f:
        f.write(response.text)
        
    # 4. 可以打印response观察对象类型
    print(type(response))
    # text方法默认打印的返回数据的json格式
    print(response1.text)
    
    # 默认打印的是返回数据二进制数据
    print(response1.content)
    # b'{\n  "args": {}, \n  "headers": {\n    "Accept": "*/*", \n    "Accept-Encoding": "gzip, deflate", \n    "Host": "httpbin.org", \n    "User-Agent": "python-requests/2.23.0", \n    "X-Amzn-Trace-Id": "Root=1-5f818280-636d615a13bf7f173724951b"\n  }, \n  "origin": "106.121.5.147", \n  "url": "http://httpbin.org/get"\n}\n'
    
    • 返回结果展示
      在这里插入图片描述
  • POST请求

    # 1. URL
    URL = 'http://httpbin.org/post'
    # 2. request对象
    json_dict = {
         
        'user': '吴亦凡'
    }
    # 传入数据 data:表单数据  json:json数据
    # response = requests.post(URL, data=json_dict)
    # response = requests.get(url,params=json_dict)
    response = requests.post(URL, json=json_dict)
    # 3. 写入文件
    with open('test1.html', 'w', encoding='utf-8') as f:
        f.write(response.text)
    
    • 返回结果
      在这里插入图片描述
  • 响应对象相关属性说明

    # 1.获取响应对象的数据 text(requests 会使用其推测的文本编码)->string类型
    response.text
    # 2.获取响应对象的数据 content->bytes类型
    # decode() 将 bytes-> str
    response.content.decode()
    # 3.前端返回状态码(无论数据是否验证正确,都会返回200状态码,测试判断不能用状态码)
    response.status_code
    # 4.前后端分离开发模式下,存在一个问题无论数据是否验证正确,都会返回200状态码,测试判断不能用状态码  
    # 测试网站登录功能,接口规定登录成功返回json->{'code':0 ,'msg':oK}
    # 4.1获取响应对象的 json数据---json()
    response.json()
    # 5.获取请求头信息
    response.requests.headers
    # 6.获取响应头信息
    response.headers
    # =====防止被反爬添加请求头的信息====
    # 添加请求头信息
    headers = {
         
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36'
    }
    request.get(url, headers=headers)
    
  • Cookie请求

    cookie作用:1. 常用与用户登录后,登录状态信息的保存 2. 缓存一些其他信息

    # ===方法1:request对象中携带cookies====
    # 1. url
    url = 'http://httpbin.org/cookies'
    # 2. 定义cookie值  dict:强制类型转换
    cookies = dict(cokie_is='Richerd')
    # 3. response加上cookie值
    # response = requests.post(URL, data=cookies)
    response = requests.get(url, cookies=cookies)
    # print(response.text)
    # 4. 写入文件
    with open('test1.html', 'w', encoding='utf-8') as f:
        f.write(response.text)
        
    # ===方法2: 直接使用cookie中的RequestsCookieJar()===
    # 这里引入 request.cookie
    # 1.实例化cookie_jar对象
    jar = requests.cookies.RequestsCookieJar()
    # 2.设置cookie
    # jar.set(请求头key值, value值, 域名, 路径)
    jar.set('coo', 'zhenxiang', domain='httpbin.org', path='/cookies')
    # 3.url
    url = 'http://httpbin.org/cookies'
    # 4.获取对象
    response = requests.get(url, cookies=jar)
    print(response.text)
    
  • Session请求

    seesion作用:和cookie类似用于保存一些信息,但浏览器中往往存的是seesionid值,真正的session信息存储在数据库中

    request模块中Session和Cookie的请求登录的区分

    • request.get()

    requests.get() 就可以发送请求, 但是 遇到涉及登录的时候, 应该先发送登录请求->登录成功获取cookies->可以去请求需要登录认证的页面

    * 1.login请求: 携带账户和密码 response = requests.post(url, json=xxx)
    * 2.解析登录成功的:cookie   = response.request._cookies
    * 3.登录用户中心请求 '/mytaobao...':requests.get('<https://i.taobao.com/my_taobao.htm?spm=xxxx', cookies=cookies)
    
    • session.get()
      • 1.先访问的是login的请求-- 携带账户和密码 response = session.post()
      • 2.再发送 info 请求 – session.get(‘info’)
    from requests import Session
    
    # 1.创建session对象
    s = Session()
    # 2.发送带cookie的请求  用url设置一个cookie值 之后的cookie将会一直和session对象绑定
    s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
    # 3.获取cookie值 检查是否获取成功
    r = s.get("http://httpbin.org/cookies")
    print(r.text)
    
    
    # 1. 设置 用户名和密码  即设置session对象的auth属性默认值
    s.auth = ('user', 'pass')
    # 2. 可以直接增加请求头中信息(在原有请求头字段中添加)
    s.headers.update({
         'test1': 'wangyibo'})
    # 3. 请求头中再次以参数形式添加另一个请求头信息  并检查请求头中是否已经添加成功
    # 注意这里或默认auth之前添加的信息也会一块合并到请求头中
    r = s.get('http://httpbin.org/headers', headers={
         'test2': 'yibowangzha'})
    print(r.text)
    
    • 返回结果
      在这里插入图片描述

Django单元测试

注意!:Django每次测试每次测试之前会自动创建一个和项目默认数据库名称相同的default临时数据库,而且临时数据库是复制了项目所有的表但是没有数据,测试用例测试结束后,会把临时创建的default数据库删除

说明

  • Django的单元测试模块继承自Python自带的测试基类unittest
  • postman和unitest的区别
    • Postman适用于接口测试 —>黑盒测试
    • unitest适用于代码逻辑测试 —>白盒测试

数据库环境准备

在Django的settings配置文件中进行对测试数据库配置

DATABASES = {
   
    'default': {
   
        'ENGINE': 'django.db.backends.mysql',  
        'HOST': '127.0.0.1', 
        'PORT': 3306,  
        'USER': 'root',  
        'PASSWORD': 'mysql',  
        'NAME': 'mysql',
        'OPTION': {
   'charset': 'utf8'},
      
       # 配置测试的数据库
       # 1.单元测试需要使用的数据库,测试执行时,会自动创建新的default数据库包含TEST库 
       # 2.每次自动创建的数据库中没有测试数据,而且测试执行完会自动删除测试数据库
       # 3.如果和default配置相同,使用默认配置
        'TEST':{
   
          'NAME':'test',
          'CHARSET': 'utf8',  # 设置测试数据库的字符集
          'COLLATION': 'utf8_general_ci',  # 测试数据表中的行的编码 
        }, 
    },
}

Testcase

注意事项!!!

  1. 由于使用的是Django自带的测试模块,所以所有的测试代码都必须在项目的目录下,且为Python的package
  2. 创建的测试函数函数名组成格式 test_xxx
  3. 执行方式为终端执行 python manage.py test 默认一键执行所有的测试代码
  • 执行摸个应用的测试 python manage.py 应用名
  • 执行应用下的某个测试文件 python manage.py 应用名.test_xxx
  • 执行应用下测试文件中的具体测试类 python manage.py 应用名.test_xxx.Demotest
  • 具体到函数 执行应用下测试文件中的具体测试类 python manage.py 应用名.test_xxx.Demotest.test_xxx

setUp和tearDown函数

  • setUp tearDown

    setUp 和 tearDown函数作用就是在测试用例代码执行前/后 做一些准备动作 !!!每个测试用例执行前后都会执行

    使用场景:测试之前打开文件 测试之后关闭文件

    class TestDemo(TestCase):
    
        def setUp(self):
            print('---setup---')
    
        def tearDown(self) -> None:
            print('---tearDown---\n')
    
        def test_two(self):
            print('---222---')
    
        def test_three(self):
            print('---3333---')
    
        def test_four(self):
            print('---4444---')
    
    
    class TestDemo2(TestCase):
    
        def test_two(self):
            print('\n---TestDemo---')
    

    测试结果:

    ---setup---
    ---4444---
    ---tearDown---
    
    ---setup---
    ---3333---
    ---tearDown---
    
    ---setup---
    ---222---
    ---tearDown---
    
    
    ---TestDemo---
    
    
  • @classmthod修饰

    setUpclass 和 tearDownclass 函数在这个类中的所有测试用例执行前后只会执行一次

    使用场景:测试用例测试之前数据库中添加测试数据

    class ThreeTest(TestCase):
    
        @classmethod
        def setUpClass(cls):
            print('setUpClass--每个测试用例类---调用一次')
    
        @classmethod
        def tearDownClass(cls):
            print('tearDownClass---每个测试用例类---调用一次')
    
        def test_baidu(self):
            url = 'http://www.baidu.com'
            response = requests.get(url)
            print(response.status_code)
    
        def test_tencent(self):
            url = 'http://www.tencent.com'
            response = requests.get(url)
            print(response.status_code)
    

    返回结果:

    setUpClass--每个测试用例类---调用一次
    200
    200
    tearDownClass---每个测试用例类---调用一次
    
  • 登录测试

    class LoginTest(TestCase):
    
        def test_login(self):
            url = 'http://www.heiheihei.site:8000/login/'
            json_dict = {
         'username': 'wangyibo', 'password': '12345678'}
            response = requests.post(url, json=json_dict)
            print(response.content.decode())
            
        
    # 登录成功返回json字符串
    {
         "code": 0
  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ricerd_S

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值