Django开发实战之单元测试和集成测试之编写测试用例以及代码覆盖率统计分析

这里分为了两种情况:
E2E:接近真实使用情况,用例数量少
UT:执行速度快,用例数量多

1、整理测试点

1、注册功能
  • 允许匿名访问
  • URL:http://127.0.0.1:8000/accounts/register/
  • get请求:返回html
  • post请求:提交json参数,返回json响应
  • 用户名不能为空
  • 密码不能为空
  • 两次密码必须相同
  • 密码长度不能小于6
  • 用户名不能重复
  • 参数正确,则返回:注册成功
2、登录
  • 允许匿名访问

  • URL:http://127.0.0.1:8000/accounts/register/

  • get请求:返回html

  • post请求:提交表单,返回了重定向

  • 用户名不能为空

  • 密码不能为空

  • 密码不能错误

3、提交反馈
  • 不允许匿名访问

  • URL:http://127.0.0.1:8000/lili/submit/

  • GET:返回HTML

  • POST::提交json,返回json

    • 提交的数据会入库
    • 提交的数据会和用户关联
    • 同一用户,不可重复发布
4、反馈的结果
  • 允许匿名访问
  • URL:http://127.0.0.1:8000/lili/result/
  • 所有的请求返回:HTML

2、编写测试代码

主要学习两个部分的内容
1、django自带的测试组件
2、pytest-django插件

1、测试http请求

在这里插入图片描述
这个Client自己是一个客户端,同时也是一个服务端

import pytest
from django.http import HttpResponse
from django.test.client import Client

# Create your tests here.


@pytest.fixture
def client()->Client:
    return Client()


def test_register(client:Client):
    res:HttpResponse = client.get('/accounts/register/')
    assert res.status_code ==200
    html:str=res.content.decode('utf-8')
    assert "账号" in html
    assert "密码" in html
    assert "确认密码" in html

执行:pytest
得到下面的结果
在这里插入图片描述

2、测试db数据库
import pytest
from django.contrib.auth.models import User
from django.http import HttpResponse
from django.test.client import Client


@pytest.fixture
def user(_django_db_helper):
    new_user = User.objects.create_user(
        username="lili01",
        password="123456",
        email="lili01@qq.com"
    )
    """这里是作为fixture的返回值,接下来创建测试用例"""
    return new_user


def test_user(user):
    """这样每个都需要加"""
    pass

其中_django_db_helper目的是为了进行数据准备,比如说在数据库中创建数据

import json

import pytest
from django.contrib.auth.models import User
from django.http import HttpResponse
from django.test.client import Client

from lili.models import Feedback


# Create your tests here.


@pytest.fixture
def client()->Client:
    return Client()


def test_register(client:Client):
    res:HttpResponse = client.get('/accounts/register/')
    assert res.status_code ==200
    html:str=res.content.decode('utf-8')
    assert "账号" in html
    assert "密码" in html
    assert "确认密码" in html

@pytest.fixture
def user(_django_db_helper):
    new_user = User.objects.create_user(
        username="lili01",
        password="123456",
        email="lili01@qq.com"
    )
    """这里是作为fixture的返回值,接下来创建测试用例"""
    return new_user

@pytest.mark.parametrize("data,code,message",[
    ({"username":"lili02",
      "password":"",
       "password_confirm":"123456",
       "email":"lili02@qq.com"
      },-1,"password不能为空"),
({"username":"lili02",
      "password":"1234567",
       "password_confirm":"123456",
       "email":"lili02@qq.com"
      },-2,"两次密码必须相同"),
({"username":"lili02",
      "password":"12345",
       "password_confirm":"12345",
       "email":"lili02@qq.com"
      },-3,"密码长度必须大于等于6"),
({"username":"lili01",
      "password":"123456",
       "password_confirm":"123456",
       "email":"lili01@qq.com"
      },-4,"用户已经存在,请重新注册"),
])
def test_register_post(user, client:Client,data,code,message):
    """这样每个都需要加"""
    res:HttpResponse  = client.post('/accounts/register/',data=data,content_type='application/json')
    html = res.content.decode('utf-8')
    res_json = json.loads(html)
    assert res_json['code'] == code
    assert res_json['message'] == message

除此以外,我们也可以对数据库进行断言,比如断言用户等于1

@pytest.mark.parametrize("data,code,message", [
    ({"username": "lili02",
      "password": "",
      "password_confirm": "123456",
      "email": "lili02@qq.com"
      }, -1, "password不能为空"),
    ({"username": "lili02",
      "password": "1234567",
      "password_confirm": "123456",
      "email": "lili02@qq.com"
      }, -2, "两次密码必须相同"),
    ({"username": "lili02",
      "password": "12345",
      "password_confirm": "12345",
      "email": "lili02@qq.com"
      }, -3, "密码长度必须大于等于6"),
    ({"username": "lili01",
      "password": "123456",
      "password_confirm": "123456",
      "email": "lili01@qq.com"
      }, -4, "用户已经存在,请重新注册"),
])
def test_register_post(user, client: Client, data, code, message):
    # 断言用户等于1,
    user_list = list(User.objects.all())
    user_list_len = len(user_list)
    assert user_list_len == 1
    """这样每个都需要加"""
    res: HttpResponse = client.post('/accounts/register/', data=data, content_type='application/json')
    html = res.content.decode('utf-8')
    res_json = json.loads(html)
    assert res_json['code'] == code
    assert res_json['message'] == message
    if res_json['code'] == 0:
        user_list = list(User.objects.all())
        user_list_len = len(user_list)
        assert user_list_len == 4
3、自动登录

在这之前我们先测试下匿名访问这个功能,大概的思路是访问的时候返回的code不等于200,我之前的文有提到这里他会进行重定向,然后状态会变成302

def test_submit_anonymous(client: Client):
    res: HttpResponse = client.get('/lili/submit/')
    assert res.status_code == 302

开始执行,不想执行之前的用例,只执行test_submit_anonymous,可以用下面这个命令,

pytest -k test_submit_anonymous

那这种情况是没有登录的状态,接下来就来到重点,那么登录之后的状态是什么样的呢?具体要怎么做呢?请接着往下看
首先,我们需要用到@pytest.fixture,代码如下

tests.py
import json

import pytest
from django.contrib.auth.models import User
from django.http import HttpResponse
from django.test.client import Client

from lili.models import Feedback


# Create your tests here.


@pytest.fixture
def client() -> Client:
    return Client()


def test_register(client: Client):
    res: HttpResponse = client.get('/accounts/register/')
    assert res.status_code == 200
    html: str = res.content.decode('utf-8')
    assert "账号" in html
    assert "密码" in html
    assert "确认密码" in html


@pytest.fixture
def user(_django_db_helper):
    new_user = User.objects.create_user(
        username="lili01",
        password="123456",
        email="lili01@qq.com"
    )
    """这里是作为fixture的返回值,在数据库里面创建数据,接下来创建测试用例"""
    return new_user

@pytest.fixture
def user_clien(client: Client,user):
    client.force_login(user)
    return client




@pytest.mark.parametrize("data,code,message", [
    ({"username": "lili02",
      "password": "",
      "password_confirm": "123456",
      "email": "lili02@qq.com"
      }, -1, "password不能为空"),
    ({"username": "lili02",
      "password": "1234567",
      "password_confirm": "123456",
      "email": "lili02@qq.com"
      }, -2, "两次密码必须相同"),
    ({"username": "lili02",
      "password": "12345",
      "password_confirm": "12345",
      "email": "lili02@qq.com"
      }, -3, "密码长度必须大于等于6"),
    ({"username": "lili01",
      "password": "123456",
      "password_confirm": "123456",
      "email": "lili01@qq.com"
      }, -4, "用户已经存在,请重新注册"),
])
def test_register_post(user, client: Client, data, code, message):
    # 断言用户等于1,
    user_list = list(User.objects.all())
    user_list_len = len(user_list)
    assert user_list_len == 1
    """这样每个都需要加"""
    res: HttpResponse = client.post('/accounts/register/', data=data, content_type='application/json')
    html = res.content.decode('utf-8')
    res_json = json.loads(html)
    assert res_json['code'] == code
    assert res_json['message'] == message
    if res_json['code'] == 0:
        user_list = list(User.objects.all())
        user_list_len = len(user_list)
        assert user_list_len == 4



def test_submit_anonymous(client: Client):
    res: HttpResponse = client.get('/lili/submit/')
    """没有登录会重定向到登录界面"""
    assert res.status_code == 302


def test_submit_login(user_clien: Client):
    res: HttpResponse = user_clien.get('/lili/submit/')
    html: str = res.content.decode('utf-8')
    assert "商品质量" in html
    assert "客服态度" in html
    assert res.status_code == 200

在这里插入图片描述
接下来result这个接口的测试,我们把所有的方法都涵盖进去:
代码就是

tests.py
import json

import pytest
from django.contrib.auth.models import User
from django.http import HttpResponse
from django.test.client import Client

from lili.models import Feedback
@pytest.mark.parametrize("methond", ["get","post","delete","put"])
def test_result_all(client: Client,methond):
    res: HttpResponse = client.generic(methond.upper(),'/lili/result/')
    html: str = res.content.decode('utf-8')
    assert res.status_code == 200

然后控制台允许用例

 pytest -k test_result_all

3、分析和统计测试覆盖率

在pytets.ini这个文件里面加入这么一行内容

addopts = --cov=lili

在这里插入图片描述
然后终端执行:pytest
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如何知道有哪17行代码没有覆盖到呢
继续修改pytets.ini这个文件里面加入这么一行内容

addopts = --cov=lili --cov-report html

然后运行:pytest
在这里插入图片描述
打开路径:D:\cekai\xuexi\Tesla\htmlcov\index.html
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/609660.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux 用户进程启动与Systemd

Linux用户空间的启动 我们都知道,Linux在内核的初始化自身的流程结束后,就会将程序流的运行转到用户态,也就是进入init进程流之后,他会按照这个流程进行初始化: init进程初始化 基础的底层服务:比如说ude…

JavaScript 事件

在 Web 开发中,JavaScript 事件是至关重要的概念之一。通过事件,我们可以实现交互性和动态性,使用户与网页进行互动。本篇博客将介绍 JavaScript 事件的基础知识,并深入探讨一些高级技术。 1. 什么是事件? 事件是指用…

振弦采集仪在岩土工程监测中的性能评价及标准选择

振弦采集仪在岩土工程监测中的性能评价及标准选择 河北稳控科技振弦采集仪是一种重要的岩土工程监测仪器,用于测量振动场的频率、振幅和相位等参数。它在岩土工程施工和地震监测中具有重要的应用价值。本文将对振弦采集仪的性能评价及标准选择进行详细介绍。 首先&…

每日一练2024.5.9

题目: 给定一个非负整数数组 nums, nums 中一半整数是 奇数 ,一半整数是 偶数 。 对数组进行排序,以便当 nums[i] 为奇数时,i 也是 奇数 ;当 nums[i] 为偶数时, i 也是 偶数 。 你可以返回 …

Java | Leetcode Java题解之第80题删除有序数组中的重复项II

题目&#xff1a; 题解&#xff1a; class Solution {public int removeDuplicates(int[] nums) {int n nums.length;if (n < 2) {return n;}int slow 2, fast 2;while (fast < n) {if (nums[slow - 2] ! nums[fast]) {nums[slow] nums[fast];slow;}fast;}return sl…

Python 全栈系列242 踩坑记录:租用算力机完成任务

说明 记一次用算力机分布式完成任务的坑。 内容 1 背景 很早的时候&#xff0c;做了一个实体识别模型。这个模型可以识别常见的PER、ORG、LOC和TIME几种类型实体。 后来&#xff0c;因为主要只用来做PER、ORG的识别&#xff0c;于是我根据业务数据&#xff0c;重新训练了模…

免费矢量图标汇总:一文掌握10个优质网站!

矢量图标是我们日常设计应用程序和网页过程中不可缺少的元素之一。通过小矢量图标&#xff0c;我们可以快速方便地实现视觉指导和功能划分。但在创作中&#xff0c;设计师往往需要花费大量的时间和精力来寻找不同网站的矢量图标&#xff0c;以满足他们的设计需求&#xff0c;这…

跨域问题(服务器和浏览器之间)待补充

一、为什么产生&#xff1a; 同源策略&#xff08;域名&#xff0c;协议&#xff0c;端口&#xff09;&#xff0c;安全问题 二、怎么解决&#xff1a; 1、cros:修改响应头 2、jp&#xff1a;采用js标签 3、代理&#xff08;创建服务器&#xff0c;定义规则&#xff0c;服…

就业班 第三阶段(zabbix) 2401--5.9 day1 普通集zabbix 5.0部署 nginx部署+agent部署

文章目录 环境一、zabbix 5.0 部署1、安装yum源2、安装相关软件3、数据库安装和配置mariaDB数据库mysql57数据库 安装mysql万能卸载mysql代码&#xff1a;启动mysql并初始化4、数据表导入5、修改配置&#xff0c;启动服务6、配置 web GUI7、浏览器访问注意数据加密的选项不要勾…

走进CHEN MEI HUA的设计哲学:书写东方女性力量与态度的时尚篇章

在时尚的舞台中央&#xff0c;品牌不止是商品&#xff0c;更是故事的讲述者、文化的传承者。CHEN MEI HUA&#xff0c;一个源自中国上海的高端女装品牌&#xff0c;以其独特的设计理念及文化内核&#xff0c;成为了时尚界一颗耀眼的明珠。今天&#xff0c;让我们一起走进CMH的世…

[android]Activity生命周期

andorid app 开发入门与项目实战

SH150S1光电吊舱

SH150S1光电吊舱 1产品应用 SH150S1是一款三轴三光吊舱&#xff0c;集成了最远测程达3.0km&#xff0c;精度小于2米的半导体激光测距机&#xff0c;640512高分辨率红外相机&#xff0c;30倍光学变倍可见光相机以及高稳定精度平台框架&#xff1b;可安装于中小型无人机&#x…

2024数维杯数学建模A题B题C题思路+模型+代码(开赛后第一时间更新)

2024数维杯数学建模A题B题C题思路模型代码&#xff08;开赛后第一时间更新&#xff09; https://mbd.pub/o/bread/ZpWakpdq https://mbd.pub/o/bread/ZpWakpdq 2024年第九届数维杯大学生数学建模挑战赛参赛规则 竞赛要求及论文提交方式; ①本次参赛作品统一在线提交到竞赛…

海外邮件群发工具的使用方法?有哪些限制?

海外邮件群发工具怎么选择&#xff1f;使用邮件群发工具的优势&#xff1f; 海外邮件群发工具成为了企业开展海外推广、联系客户、推广产品和服务的重要工具。但如何有效地使用这一工具&#xff0c;成为了众多营销人员关注的问题。接下来&#xff0c;AokSend将详细探讨海外邮件…

两种方法合并3dtiles(分别使用js/java)

目录 前言&#xff1a; 需合并的json目录 aa/tileset.json bb/tileset.json cc/tileset.json dd/tileset.json ee/tileset.json js源码&#xff1a; 运行命令&#xff1a; 生成结果&#xff1a; java源码&#xff1a; Matrix.java ThreeDTilesJoin2.java pom文件…

解析Spring中的循环依赖问题:初探三级缓存

什么是循环依赖&#xff1f; 这个情况很简单&#xff0c;即A对象依赖B对象&#xff0c;同时B对象也依赖A对象&#xff0c;让我们来简单看一下。 // A依赖了B class A{public B b; }// B依赖了A class B{public A a; }这种循环依赖可能会引发问题吗&#xff1f; 在没有考虑Sp…

从古代故事中领悟高情商回话

页面 页面代码 <% layout(/layouts/default.html, {title: 故事管理, libs: [dataGrid]}){ %> <div class"main-content"><div class"box box-main"><div class"box-header"><div class"box-title">&l…

ChatGPT开源的whisper音频生成字幕

1、前言 好了&#xff0c;那接下来看一下whisper开源库的介绍 有五种模型大小&#xff0c;其中四种仅支持英语&#xff0c;提供速度和准确性的权衡。上面便是可用模型的名称、大致的内存需求和相对速度。如果是英文版的语音&#xff0c;直接想转换为英文。 本来我是想直接在我的…

Java 变量类型

Java 变量类型 在 Java 语言中&#xff0c;所有的变量在使用前必须声明。 声明变量的基本格式如下&#xff1a; type identifier [ value][, identifier [ value] …] ; 格式说明&#xff1a; type – 数据类型。 identifier – 是变量名&#xff0c;可以使用逗号 , 隔开来…