测试工具coverage的高阶使用

  在文章Python之单元测试使用的一点心得中,笔者介绍了自己在使用Python测试工具coverge的一点心得,包括:

  1. 使用coverage模块计算代码测试覆盖率
  2. 使用coverage api计算代码测试覆盖率
  3. coverage配置文件的使用
  4. coverage badge的生成

  本文在此基础上,将会介绍coverage的高阶使用,包括:

  • Flask API测试
  • coverage多文件测试
  • coverage的Gitlab CI/CD集成
  • coverage badge生成

  本文中使用coverage的版本均为7.3.0。

Flask API测试

  在unittest测试框架如果对Flask API进行测试时使用HTTP请求,那么将无法得到代码覆盖率。
  我们有如下的示例Flask服务:

# -*- coding: utf-8 -*-
from flask import Flaskapp = Flask(__name__)@app.route('/')
def index():return "Hello index"@app.route('/test')
def test():return "Hello test"if __name__ == '__main__':app.run(host="0.0.0.0", port=5000, debug=True)

  正确的测试代码如下:

# -*- coding: utf-8 -*-
import unittestfrom flask_app import appclass AppTestCase(unittest.TestCase):def setUp(self):self.ctx = app.app_context()self.ctx.push()self.client = app.test_client()def tearDown(self):self.ctx.pop()def test_case1(self):response = self.client.get("/")self.assertEqual(response.status_code, 200)self.assertEqual(response.text, "Hello index")def test_case2(self):response = self.client.get("/test")self.assertEqual(response.status_code, 200)self.assertEqual(response.text, "Hello test")if __name__ == "__main__":suite = unittest.TestSuite()suite.addTest(AppTestCase('test_case1'))suite.addTest(AppTestCase('test_case2'))run = unittest.TextTestRunner()run.run(suite)

coverage多文件测试

  我们有如下的实现两个变量相加的代码(func_add.py):

# -*- coding: utf-8 -*-
def add(a, b):if isinstance(a, str) and isinstance(b, str):return a + '+' + belif isinstance(a, list) and isinstance(b, list):return a + belif isinstance(a, (int, float)) and isinstance(b, (int, float)):return a + belse:return None

  两个测试文件test_func_add1.pytest_func_add2.py,内容如下:

# -*- coding: utf-8 -*-
import unittestfrom func_add import addclass TestAdd(unittest.TestCase):def setUp(self):passdef test_add_case1(self):a = "Hello"b = "World"res = add(a, b)print(res)self.assertEqual(res, "Hello+World")def test_add_case2(self):a = 1b = 2res = add(a, b)print(res)self.assertEqual(res, 3)if __name__ == '__main__':# 部分用例测试# 构造一个容器用来存放我们的测试用例suite = unittest.TestSuite()# 添加类中的测试用例suite.addTest(TestAdd('test_add_case1'))suite.addTest(TestAdd('test_add_case2'))run = unittest.TextTestRunner()run.run(suite)
# -*- coding: utf-8 -*-
import unittestfrom func_add import addclass TestAdd(unittest.TestCase):def setUp(self):passdef test_add_case3(self):a = [1, 2]b = [3]res = add(a, b)print(res)self.assertEqual(res, [1, 2, 3])def test_add_case4(self):a = 2b = "3"res = add(a, b)print(None)self.assertEqual(res, None)if __name__ == '__main__':# 部分用例测试# 构造一个容器用来存放我们的测试用例suite = unittest.TestSuite()# 添加类中的测试用例suite.addTest(TestAdd('test_add_case3'))suite.addTest(TestAdd('test_add_case4'))run = unittest.TextTestRunner()run.run(suite)

使用命令进行测试:

coverage run test_func_add1.py
coverage run test_func_add2.py
coverage report

生成的代码测试覆盖率如下:

Name          Stmts   Miss  Cover
---------------------------------
func_add.py       8      2    75%
---------------------------------
TOTAL             8      2    75%

这是不符合我们预期的,因为在这两个测试文件中我们对所有的代码都进行了测试,理论上测试覆盖率应该为100%,之所以这样,是因为coverage run命令运行时每一次都会覆盖掉之前的测试。正确的测试命令(以文件追加的形式)如下:

coverage run test_func_add1.py
coverage run --append test_func_add2.py
coverage report

此时代码覆盖率如下:

Name          Stmts   Miss  Cover
---------------------------------
func_add.py       8      0   100%
---------------------------------
TOTAL             8      0   100%

coverage的Gitlab CI/CD集成

  在文章Gitlab CI/CD入门(一)Python项目的CI演示中,笔者介绍了Gitlab CI/CD的入门。在此基础上,我们将集成coverage。
  首先我们的test目录如下:

.
├── __init__.py
├── func_add.py
└── test_func_add.py

func_add.py为实现两个变量相加的代码,如前述。test_func_add.py为测试代码,如下:

# -*- coding: utf-8 -*-
import unittestfrom func_add import addclass TestAdd(unittest.TestCase):def setUp(self):passdef test_add_case1(self):a = "Hello"b = "World"res = add(a, b)print(res)self.assertEqual(res, "Hello+World")def test_add_case2(self):a = 1b = 2res = add(a, b)print(res)self.assertEqual(res, 3)def test_add_case3(self):a = [1, 2]b = [3]res = add(a, b)print(res)self.assertEqual(res, [1, 2, 3])def test_add_case4(self):a = 2b = "3"res = add(a, b)print(None)self.assertEqual(res, None)if __name__ == '__main__':# 部分用例测试# 构造一个容器用来存放我们的测试用例suite = unittest.TestSuite()# 添加类中的测试用例suite.addTest(TestAdd('test_add_case1'))suite.addTest(TestAdd('test_add_case2'))suite.addTest(TestAdd('test_add_case3'))suite.addTest(TestAdd('test_add_case4'))run = unittest.TextTestRunner()run.run(suite)

CI/CD依赖.gitlab-ci.yml,配置如下:

stages:- build- unittestbuild-job:stage: buildscript:- echo `date`- echo "Hello, $GITLAB_USER_LOGIN!"- echo "This job deploys something from the $CI_COMMIT_BRANCH branch."unit_test_job:stage: unittestimage: python:3.9-alpine3.17script:- pip3 install coverage==7.3.0- coverage run test/test_func_add.py- coverage reportcoverage: '/TOTAL.*\s+(\d+%)$/'

  运行CI/CD,结果如下图:
unittest_job运行结果
  在Gitlab项目中的Settings -> CI/CD -> General pipelines中点击Expand,会显示CI/CD已内置Pipeline status, Coverage report, Latest release,其中Coverage repor如下图:
Coverage report
  最后我们要在项目中加入coverage badge(徽章),在Gitlab项目中的Settings -> General -> Badge中点击Expand,再点击Add badge,coverage徽章的配置如下:
Add badge
本项目中只有main分支,因此不需要设置变量,实际在使用过程中,需要配置变量如default_branch等。
  以上配置完毕后,项目徽章显示如下:

成功加入徽章!
  以上配置过程已开源,项目网址为:https://gitlab.com/jclian91/gitlab_ci_test 。

coverage badge生成

  coverage badge生成方式分为静态和动态。
  动态的话,可使用coverage-badge或者genbadge模块。
  静态的话,可使用网站:https://shields.io/badges/static-badge .
  比如我们生成编程语言的徽章,如下图:
示例徽章生成
之后我们就可以用该网址访问徽章了。

总结

  本文介绍了测试工具coverage的高阶使用,希望能对读者有所启发~

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Leetcode】103.二叉树的锯齿形层序遍历

一、题目 1、题目描述 给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。 示例1: 输入:root = [3,9,20,null,null,15,7] 输出:[[3],[20,9],[15,7]]示例2: 输入:root = [1] 输…

hive-无法启动hiveserver2

启动hiveserver2没有反应&#xff0c;客户端也无法连接( beeline -u jdbc:hive2://node01:10000 -n root) 报错如下 查看hive的Log日志&#xff0c;发现如下报错 如何解决 在hive的hive_site.xml中添加如下代码 <property><name>hive.server2.active.passive…

论文笔记:Continuous Trajectory Generation Based on Two-Stage GAN

2023 AAAI 1 intro 1.1 背景 建模人类个体移动模式并生成接近真实的轨迹在许多应用中至关重要 1&#xff09;生成轨迹方法能够为城市规划、流行病传播分析和交通管控等城市假设分析场景提供仿仿真数据支撑2&#xff09;生成轨迹方法也是目前促进轨迹数据开源共享与解决轨迹数…

fiddler抓包问题记录,支持https、解决 tunnel to 443

fiddler下载安装步骤及基本配置 fiddler抓包教程&#xff0c;如何抓取HTTPS请求&#xff0c;详细教程 可能遇到的问题及解决方案 1. 不能正常访问页面&#xff08;所有https都无法访问&#xff09; 解决方案&#xff1a;查看下面配置是否正确 Rules-customization 找到 OnB…

不是说嵌入式是风口吗,那为什么工作还那么难找?

最近确实有很多媒体、机构渲染嵌入式可以拿高薪&#xff0c;这在行业内也是事实&#xff0c;但前提是你有足够的竞争力&#xff0c;真的懂嵌入式。 时至今日&#xff0c;能做嵌入式程序开发的人其实相当常见&#xff0c;尤其是随着树莓派、Arduino等开发板的普及&#xff0c;甚…

el-table实现懒加载(el-table-infinite-scroll)

2023.8.15今天我学习了用el-table对大量的数据进行懒加载。 效果如下&#xff1a; 1.首先安装&#xff1a; npm install --save el-table-infinite-scroll2 2.全局引入&#xff1a; import ElTableInfiniteScroll from "el-table-infinite-scroll";// 懒加载 V…

ansible(1)-- 部署ansible连接被控端

目录 一、部署ansible 1.1 安装 1.2 测试连接 192.168.136.55 ansible 192.168.136.56被控端 一、部署ansible 1.1 安装 zabbix-s只是主机名&#xff0c;不用在意&#xff0c;更好该主机也安装了zabbix&#xff0c;不好更改。 下载阿里云epel源 #安装阿里云的epel源&#…

机器学习笔记 - 基于keras + 小型Xception网络进行图像分类

一、简述 Xception 是深度为 71 层的卷积神经网络,仅依赖于深度可分离的卷积层。 论文中将卷积神经网络中的 Inception 模块解释为常规卷积和深度可分离卷积运算(深度卷积后跟点卷积)之间的中间步骤。从这个角度来看,深度可分离卷积可以理解为具有最大数量塔的 Inception 模…

websocker无法注入依赖

在公司中准备用websocker统计在线人数&#xff0c;在WebSocketServer使用StringRedisTemplate保存数据到redis中去&#xff0c;但是在保存的时候显示 StringRedisTemplate变量为null 详细问题 2023-08-20 10:37:14.109 ERROR 28240 --- [nio-7125-exec-1] o.a.t.websocket.po…

Python爬虫的scrapy的学习(学习于b站尚硅谷)

目录 一、scrapy  1. scrapy的安装  &#xff08;1&#xff09;什么是scrapy  &#xff08;2&#xff09;scrapy的安装 2. scrapy的基本使用  &#xff08;1&#xff09;scrap的使用步骤  &#xff08;2&#xff09;代码的演示 3. scrapy之58同城项目结构和基本方法&…

网络安全---webshell实践

一、首先环境配置 1.上传文件并解压 2.进入目录下 为了方便解释&#xff0c;我们只用两个节点&#xff0c;启动之后&#xff0c;大家可以看到有 3 个容器&#xff08;可想像成有 3 台服务器就成&#xff09;。 二、使用蚁剑去连接 因为两台节点都在相同的位置存在 ant.jsp&…

CI/CD入门(二)

CI/CD入门(二) 目录 CI/CD入门(二) 1、代码上线方案 1.1 早期手动部署代码1.2 合理化上线方案1.3 大型企业上线制度和流程1.4 php程序代码上线的具体方案1.5 Java程序代码上线的具体方案1.6 代码上线解决方案注意事项2、理解持续集成、持续交付、持续部署 2.1 持续集成2.2 持续…

政务中心站至政务中心东站右线盾构本月始发

本报记者 赵鹏 实习记者 池阳 通讯员 董浩程 立秋已过&#xff0c;平谷线“瓜熟蒂落”的日子指日可待。在左线隧道刚刚顺利贯通后&#xff0c;平谷线政务中心站至政务中心东站区间右线隧道已展开盾构组装施工&#xff0c;右线盾构即将于本月内始发&#xff0c;被誉为“地下蛟龙…

若依项目的介绍(前后端分离版本)

目录 一、若依介绍 &#xff08;一&#xff09;简单介绍 &#xff08;二&#xff09;若依版本 &#xff08;三&#xff09;Git远程拉取步骤 二、项目的技术介绍 &#xff08;一&#xff09;后端技术 1.spring boot 2.Spring Security安全控制 3.MyBatis 4.MySQL和R…

Jenkins+Jmeter集成自动化接口测试并通过邮件发送测试报告

一、Jenkins的配置 1、新增一个自由风格的项目 2、构建->选择Excute Windows batch command&#xff08;因为我是在本地尝试的&#xff0c;因此选择的windows&#xff09; 3、输入步骤&#xff1a; 1. 由于不能拥有相同的jtl文件&#xff0c;因此在每次构建前都需要删除jtl…

badgerdb里面的事务

事务的ACID A 原子性&#xff08;Atomicity&#xff09; 多步骤操作&#xff0c;只能是两种状态&#xff0c;要么所有的步骤都成功执行&#xff0c;要么所有的步骤都不执行&#xff0c;举例说明就是小明向小红转账30元的场景&#xff0c;拆分成两个步骤&#xff0c;步骤1&#…

Azure不可变Blob存储

文章目录 Azure不可变Blob存储介绍Azure不可变性策略实战演练 Azure不可变Blob存储介绍 不可变的存储是一种用于存储业务关键型 Blob 数据的存储方式。与可变存储相反&#xff0c;不可变存储的特点是一旦数据被写入后&#xff0c;便无法再对其进行修改或删除。这种存储方式提供…

Ruby软件外包开发语言特点

Ruby 是一种动态、开放源代码的编程语言&#xff0c;它注重简洁性和开发人员的幸福感。在许多方面都具有优点&#xff0c;但由于其动态类型和解释执行的特性&#xff0c;它可能不适合某些对性能和类型安全性要求较高的场景。下面和大家分享 Ruby 语言的一些主要特点以及适用的场…

最优化方法Python计算:牛顿算法

设函数 f ( x ) f(\boldsymbol{x}) f(x)&#xff0c; x ∈ R n \boldsymbol{x}\in\text{ℝ}^n x∈Rn二阶连续可微&#xff0c;记 g ( x ) ∇ f ( x ) \boldsymbol{g}(\boldsymbol{x})\nabla f(\boldsymbol{x}) g(x)∇f(x)&#xff0c; H ( x ) ∇ 2 f ( x ) \boldsymbol{H}(\…

npm install ffi各种失败,换命令npm i ffi-napi成功

网上各种帖子安装ffi&#xff0c;基本上到了windows build tools这里会卡住。 使用命令npm install --global --production windows-build-tools 安装报错信息如下&#xff1a; PS E:\codes\nodejsPath\tcpTest> npm install --global --production windows-build-tools …