Web项目如何做单元测试
你可能会用单元测试框架,python的unittest、pytest,Java的Junit、testNG等。
那么你会做单元测试么!当然了,这有什么难的?
test_demo.py
def inc(x):return x + 1def test_answer():assert inc(3) == 4
inc() 是定义的一个被测函数,test_anserver() 用于测试上面的一段代码。
通过pytest运行上面的代码:
> pytest test_demo.py
====================== test session starts ======================= platform win32 -- Python 3.7.1, pytest-5.0.1, py-1.8.0, pluggy-0.12.0
rootdir: D:\vipcn\demo
plugins: cov-2.7.1, forked-1.0.2, html-1.20.0, metadata-1.8.0, ordering-0.6, parallel-0.0.9, rerunfailures-7.0, xdist-1.28.0, seleniumbase-1.23.10
collected 1 itemtest_demo.py . [100%]==================== 1 passed in 0.08 seconds ====================
单元测试不就是这么单嘛!
那么Web项目中的单元测试如何做?
我们以Django Web框架为例,它是MTV开发模式。接下来会围绕着这个模式介绍如何做测试。
模型测试
M 指models,用于定义ORM,即对象关系映射,是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。
models.py 中的代码是这样的:
from django.db import modelsclass Question(models.Model):question_text = models.CharField(max_length=200)pub_date = models.DateTimeField(auto_now=True)
这里定义了两个类,这两个类即没有入参,也没有return返回值。如何测试呢?
测试代码如下:
from django.test import TestCase
from myapp.models import Questionclass QuestionTestCase(TestCase):def setUp(self):Question.objects.create(id=1, question_text="你会做单元测试么?")def test_question(self):"""查询id=1的问题"""question = Question.objects.get(id=1)self.assertEqual(question.question_text, '你会做单元测试么?')
不知道你是否看懂了这段代码,django模型我们可以看作是数据库表,那么对于表的操作就是增删改查,这里先创建一条数据,再查询出这条数据,然后判断其字段是否正确。
参考:Writing and running tests | Django documentation | Django
视图测试
V 指views,用于接收前端发来的请求,可能需要调用数据库,把对应的数据处理之后,和HTML页面一同返回给前端。
views.py 代码如下:
from django.shortcuts import render
from .models import Questiondef index(request):latest_question_list = Question.objects.order_by('-pub_date')[:5]context = {'latest_question_list': latest_question_list}return render(request, 'polls/index.html', context)
index() 视图函数确实有入参,request包含的是客户端信息,比如请求的方法,请求的host,请求头Header等,这些客户端数据如何构造? return返回的是HTML页面,以及查询数据库的数据,如何针对这些数据写断言呢?
测试代码如下:
from django.test import TestCase
from myapp.models import Questionclass IndexTestCase(TestCase):def setUp(self):Question.objects.create(id=1, question_text="你会做单元测试么?")def test_index(self):"""测试index视图"""response = self.client.get("/index")self.assertEqual(response.status_code, 200)self.assertTemplateUsed(response, "polls/index.html")
这里假定当浏览器访问 http://127.0.0.1:8000/index 时调用到index视图,返问题列表页面。
self.client.get() 可以模拟客户端浏览器发送 request GET 请求。拿到服务端的response,判断状态码是否为 200。 self.assertTemplateUsed() 断言返回的页面是否正确。
参考:Testing tools | Django documentation | Django
模板测试
T 指Teamplate,主要是HTML页面。用户在浏览器中输入URL地址,最终会得到一个HTML页面。
index.html代码如下:
{% if latest_question_list %}<ul>{% for question in latest_question_list %}<li><a name="q" href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>{% endfor %}</ul>
{% else %}<p>No polls are available.</p>
{% endif %}
这里面的代码连个方法都没有,更别提入参和返回值了,请问怎么对HTML代码进行测试?
我们确实没有办法直接对HTML代码进行测试。不过,可以借助Selenium来做UI自动化测试,从而保证页面的正确性。
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from selenium import webdriverclass MySeleniumTests(StaticLiveServerTestCase):@classmethoddef setUpClass(cls):super().setUpClass()cls.selenium = webdriver.Chrome()cls.selenium.implicitly_wait(10)@classmethoddef tearDownClass(cls):cls.selenium.quit()super().tearDownClass()def test_index_page(self):self.selenium.get('%s%s' % (self.live_server_url, '/index'))question_list = self.selenium.find_elements_by_name("q")for q in question_list:print(q.text)
Django封装了StaticLiveServerTestCase,让你在运行UI测试时会自动启动Django服务。 所以,你可以直接使用self.live_server_url 访问django启动的服务地址。
最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:


相关文章:
Web项目如何做单元测试
你可能会用单元测试框架,python的unittest、pytest,Java的Junit、testNG等。 那么你会做单元测试么!当然了,这有什么难的? test_demo.py def inc(x):return x 1def test_answer():assert inc(3) 4 inc() 是定义的…...
MySQL主从复制(基于GTID--事务ID方式)
目录 一、GTID相关概念1.GTID 是什么?2.GTID主从复制方式概念3.GTID的优缺点 二、GTID工作原理三、部署主从复制四、测试同步1.主库上新建数据库2.从库上查看是否同步成功 五、重设从库六、常见故障七、故障切换八、GTID的一些疑问1.为什么基于GTID的同步也要打开bi…...
3.72 Command Buffer及URP概述
一、Command Buffer 1.概念 CommandBuffer携带一系列的渲染命令,依赖相机,用来拓展渲染管线的渲染效果。而且可以指定在相机渲染的某个点执行本身的拓展渲染。Command buffers也可以结合屏幕后期效果使用。 简单来说就是可以在渲染流程中插入一些自定…...
分布式理论和分布式锁知识点总结
文章目录 (一) 分布式理论算法和协议1)CAP理论总结 2)BASE理论BASE 理论的核心思想基本可用软状态最终一致性 3)Paxos算法Basic Paxos 算法4) Raft算法1 拜占庭将军 5)Gossip协议 (二) 分布式锁分布式锁应该具备哪些条…...
IOC课程整理-17 Spring事件
1. Java 事件/监听器编程模型 2. 面向接口的事件/监听器设计模式 3. 面向注解的事件/监听器设计模式 4. Spring 标准事件-ApplicationEvent 5. 基于接口的 Spring 事件监听器 6. 基于注解的 Spring 事件监听器 7. 注册 Spring ApplicationListener 8. Spring 事件发布器 9. Spr…...
大数据Flink(一百零五):SQL性能调优
文章目录 SQL性能调优 一、 MiniBatch 聚合...
ESP8266,手机与电脑之间的TCP通讯
电脑端运行通讯猫调试助手,作为服务端: 电脑端 电脑的IP地址是: 192.168.2.232 手机与电脑之间的TCP通讯 手机端运行网络调试精灵,作为客户端: 手机端 如果从手机端点击"发送"按钮,则也会将"ghhh东方红广场"几个字发送到电脑上(服务端). ESP8266作为客户…...
vue的数据监听是如何实现的?
Vue的数据监听是通过数据劫持和发布订阅模式来实现的。 数据劫持:Vue通过使用Object.defineProperty()方法来劫持数据对象的属性,并使用getter和setter来监听属性的变化。当属性被修改时,setter方法会被调用,从而触发相应的监听函…...
埋点日志解决方案——Golang+Gin+Sarama VS Java+SpringCloudGateway+ReactorKafka
埋点日志解决方案——GolangGinSarama VS JavaSpringCloudGatewayReactorKafka 之前我就写过几篇OpenRestylua-kafka-client将埋点数据写入Kafka的文章,如下: Lua将Nginx请求数据写入Kafka——埋点日志解决方案 python定时任务执行shell脚本切割Nginx…...
LeetCode 541 反转字符串 II 简单
题目 - 点击直达 1. 541 反转字符串 II 简单1. 题目详情1. 原题链接2. 题目要求3. 基础框架 2. 解题思路1. 思路分析2. 时间复杂度3. 代码实现 1. 541 反转字符串 II 简单 1. 题目详情 给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个…...
从入门到精通:深入了解CSS中的Grid网格布局技巧和应用!
🎬 江城开朗的豌豆:个人主页 🔥 个人专栏 :《 VUE 》 《 javaScript 》 📝 个人网站 :《 江城开朗的豌豆🫛 》 ⛺️ 生活的理想,就是为了理想的生活 ! 目录 ⭐ 专栏简介 📘 文章引言 一…...
Android Studio Giraffe 添加 maven { url “https://jitpack.io“ }报错
Android Studio Giraffe 添加 maven { url “https://jitpack.io” }报错 settings.gradle.kts:13:21: Unexpected tokens (use ; to separate expressions on the same line)解决方法 新版maven写法发生了改变: maven { url uri("https://jitpack.io"…...
Linux C/C++ 实现网络流量分析(性能工具)
网络流量分析的原理基于对数据包的捕获、解析和统计分析,通过对网络流量的细致观察和分析,帮助管理员了解和优化网络的性能、提高网络安全性,并快速排查和解决网络故障和问题。 Linux中的网络流量常见类型 在Linux中,网络流量可以…...
python门牌制作,统计某个数字出现的次数
题目: 小蓝要为一条街的住户制作门牌号。 这条街一共有 2022位住户,门牌号从 1 到 2022 编号。 小蓝制作门牌的方法是先制作 0 到 9 这几个数字字符,最后根据需要将字符粘贴到门牌上,例如门牌 1017 需要依次粘贴字符 1、0、1、…...
轻量封装WebGPU渲染系统示例<7>-材质多pass(源码)
当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/version-1.01/src/voxgpu/sample/MultiMaterialPass.ts 此示例渲染系统实现的特性: 1. 用户态与系统态隔离。 2. 高频调用与低频调用隔离。 3. 面向用户的易用性封装。 4. 渲染数据和渲染机制分离。 …...
0030Java程序设计-积分管理系统论文
文章目录 摘 要**目 录**系统实现系统功能需求3.2.1 管理员功能3.2.2 柜员功能 开发环境 摘 要 随着计算机和网络的不断革新,世界已经进入了前所未有的电子时代。作为实用性强、应用范围广泛的会员管理系统也正在被越来越多的各类企业用于消费管理领域。然…...
H5游戏源码分享-考眼力游戏猜猜金币在哪
H5游戏源码分享-考眼力游戏猜猜金币在哪 <!DOCTYPE html> <html> <head><meta http-equiv"Content-Type" content"text/html; charsetUTF-8"><meta charset"UTF-8"><meta name"apple-mobile-web-app-capa…...
2023 年值得关注的国外网络安全初创公司
网络安全初创公司试图解决的问题往往有点超前于主流。他们可以比大多数老牌公司更快地填补空白或新兴需求。初创公司通常可以更快地创新,因为它们不受安装基础的限制。 当然,缺点是初创公司往往缺乏资源和成熟度。公司致力于初创公司的产品或平台是有风…...
搞定蓝牙-第六篇(HID
搞定蓝牙-第六篇(HID) ble与HIDHOGPGAPP与HID ESP32程序分析 ble与HID HOGP 我们发现,电脑连接了蓝牙键盘就可以直接使用了,不需要配置任何东西,那么,这两者是怎么通讯的呢。我们使用的电脑windows系统内…...
Open3D(C++) 最小二乘拟合平面(直接求解法)
目录 一、算法原理二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。 一、算法原理 平面方程的一般表达式为: A x + B y + C...
EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
【若依】框架项目部署笔记
参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作: 压缩包下载:http://download.redis.io/releases 1. 上传压缩包,并进入压缩包所在目录,解压到目标…...
验证redis数据结构
一、功能验证 1.验证redis的数据结构(如字符串、列表、哈希、集合、有序集合等)是否按照预期工作。 2、常见的数据结构验证方法: ①字符串(string) 测试基本操作 set、get、incr、decr 验证字符串的长度和内容是否正…...
算法250609 高精度
加法 #include<stdio.h> #include<iostream> #include<string.h> #include<math.h> #include<algorithm> using namespace std; char input1[205]; char input2[205]; int main(){while(scanf("%s%s",input1,input2)!EOF){int a[205]…...
虚幻基础:角色旋转
能帮到你的话,就给个赞吧 😘 文章目录 移动组件使用控制器所需旋转:组件 使用 控制器旋转将旋转朝向运动:组件 使用 移动方向旋转 控制器旋转和移动旋转 缺点移动旋转:必须移动才能旋转,不移动不旋转控制器…...
SQL进阶之旅 Day 22:批处理与游标优化
【SQL进阶之旅 Day 22】批处理与游标优化 文章简述(300字左右) 在数据库开发中,面对大量数据的处理任务时,单条SQL语句往往无法满足性能需求。本篇文章聚焦“批处理与游标优化”,深入探讨如何通过批量操作和游标技术提…...
