深入Asyncio(十二)Asyncio与单元测试
Testing with asyncio
之前有说过应用开发者不需要将loop当作参数在函数间传递,只需要调用asyncio.get_event_loop()即可获得。但是在写单元测试时,可能会需要用多个loop(每个测试用一个单独的loop),问题来了:是否为了支持单元测试而要将loop作为函数参数传入呢?
先看个例子。
import asyncio
from typing import Callable
async def f(notify: Callable[[str], None]): # 1
# < ... some code ... >
loop = asyncio.get_event_loop() # 2
loop.call_soon(notify, 'Alert!') # 3
# < ... some code ... >
想象一个coroutine内部需要通过call_soon调用另一个函数,这个函数可能是logging,发聊天信息,短线股票操作或其它任何操作;
仍然不通过函数参数来获取loop,但要记住一点,这个方法调用始终获取的是当前线程的loop;
将回调函数及其参数添加到loop的下一次迭代中。
最佳方式是通过fixture来为异步代码提供loop,Pytest将fixtures中定义的函数返回值作为参数传入测试函数中,描述起来有些复杂,用代码展示一下。
# conftest.py # 1
import pytest
@pytest.fixture(scope='function') # 2
def loop():
loop = asyncio.new_event_loop() # 3
try:
yield loop
finally:
loop.close() # 在结束时关闭loop
Pytest将会自动导入名称为“conftest.py”的文件并使其中的配置生效;
这里创建了一个fixture,scope参数告诉Pytest这个fixture的作用范围,用function限制将会使得每个函数都获得新的loop;
创建一个全新的loop,但不会立刻让其开始运行。
上述代码有个错误,不要直接使用它,错误很微妙,但也是本章的全部要点,下面开始讨论它,先给一个测试用例。
from somewhere import f # 1
def test_f(loop): # 2
collection = [] # 3
def f_notify(msg): # 4
collection.append(msg)
loop.create_task(f(f_notify)) # 5
loop.call_later(1, loop.stop) # 6
loop.run_forever()
assert collection[0] == 'Alert!' # 7
这里当作伪代码,表示f是一个在其它模块中定义的coroutine;
Pytest会识别loop函数名并从fixtures中找到这个函数并传入它的调用返回值;
用一个容器收集notify的信息;
这是notify函数;
安排一个coroutine调用notify作为task;
因为loop是run_forever的,用call_later确保loop会停止;
此处进行测试。
上面提到有个错误,在这个导入的coroutine函数f中,loop是通过get_event_loop()获得的,而非fixture中提供的,所以这个测试会失败,因为通过get_event_loop()获得的loop压根不会运行。
一个解决办法就是明确地给函数传入loop作为参数,这样就能保证正确的loop被使用,然而这样写代码十分痛苦,因为这样一来大量的函数都要传入loop参数。
有个更好的办法就是,当一个新的loop运行时,将这个loop设置为当前线程的loop,这样get_event_loop()返回的总是最新的loop,这对单元测试十分有用。
# conftest.py
import pytest
@pytest.fixture(scope='function')
def loop():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop) # 这个方法执行后,所有后续的get_event_loop获得的都是fixture中的loop,不需要显式地将loop作为参数传入了
try:
yield loop
finally:
loop.close()
深入Asyncio(十二)Asyncio与单元测试的更多相关文章
- springboot(十二):springboot单元测试、打包部署
单元测试 1.在pom包中添加spring-boot-starter-test包引用 <dependency> <groupId>org.springframework.boo ...
- 20155322 2016-2017-2 《Java面向对象程序设计》第十二周课堂练习之Arrays和String单元测试
20155322 2016-2017-2 <Java面向对象程序设计>第十二周课堂练习之Arrays和String单元测试 练习目地 在IDEA中以TDD的方式对String类和Array ...
- Spring Boot干货系列:(十二)Spring Boot使用单元测试(转)
前言这次来介绍下Spring Boot中对单元测试的整合使用,本篇会通过以下4点来介绍,基本满足日常需求 Service层单元测试 Controller层单元测试 新断言assertThat使用 单元 ...
- python 并发专题(十三):asyncio (二) 协程中的多任务
. 本文目录# 协程中的并发 协程中的嵌套 协程中的状态 gather与wait . 协程中的并发# 协程的并发,和线程一样.举个例子来说,就好像 一个人同时吃三个馒头,咬了第一个馒头一口,就得等这口 ...
- Spring Boot(十二):spring boot如何测试打包部署
Spring Boot(十二):spring boot如何测试打包部署 一.开发阶段 1,单元测试 在开发阶段的时候最重要的是单元测试了,springboot对单元测试的支持已经很完善了. (1)在p ...
- 20155207JAVA第十二周课堂练习
20155207JAVA第十二周课堂练习 教材代码检查--P98 修改教材P98 Score2.java, 让执行结果数组填充是自己的学号 Arrays和String单元测试 在IDEA中以TDD的方 ...
- 前端开发中SEO的十二条总结
一. 合理使用title, description, keywords二. 合理使用h1 - h6, h1标签的权重很高, 注意使用频率三. 列表代码使用ul, 重要文字使用strong标签四. 图片 ...
- CRL快速开发框架系列教程十二(MongoDB支持)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- 我的MYSQL学习心得(十二) 触发器
我的MYSQL学习心得(十二) 触发器 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数 ...
- Web 前端开发精华文章推荐(jQuery、HTML5、CSS3)【系列十二】
2012年12月12日,[<Web 前端开发人员和设计师必读文章>系列十二]和大家见面了.梦想天空博客关注 前端开发 技术,分享各种增强网站用户体验的 jQuery 插件,展示前沿的 HT ...
随机推荐
- 阿里巴巴Java开发手册公开版(转)
1.不要嫌名字长 无论是方法,变量,还是函数的取名,不要嫌弃名称太长,只要能够表示清楚含义就可以了. 2.String[] args而不是String args[] 中括号是数组类型的一部分,数组定义 ...
- 自定义及发布一个webservice服务
自定义及发布一个webservice服务 - 声明 某个业务服务为webservice服务 通过@webservice 注解来声明 - 发布webservice服务 ...
- 64位linux 汇编
c源码:testg.c 1 #include<stdio.h> 2 3 #define s ...
- 刷leetcode是什么样的体验?【转】
转自:https://www.zhihu.com/question/32322023 刷leetcode是什么样的体验? https://leetcode.com/ 1 条评论 默认排序 按时间排 ...
- c# automapper 使用
一.最简单的用法 有两个类User和UserDto 1 public class User 2 { 3 public int Id { get; set; } 4 public string Name ...
- 使用证书登陆Linux服务器
CentOS 7 SSH使用证书登录 https://blog.csdn.net/long690276759/article/details/53535464 切记: 0.私钥放在client,公钥放 ...
- windows 下使用github客户端报错:Failed to publish this branch
在windows系统下使用github客户端同步的时候报错“Failed to publish this branch”,查找原因,发现结果是安装vscode的时候没有检查到git,然后安装git后库 ...
- IOS7开发~错误收集
1. fatal error: file '/Applications/Xcode5-DP.app/Contents/Developer/Platforms/iPhoneSimulator.platf ...
- 真正解决 thinkphp 验证码 出错 无法显示 问题
今天做到验证码这一块想到tp自带验证图片 大喜单鼓捣半天不出来 一直是个小 X 官方提示:如果无法显示验证码,请检查:² PHP是否已经安装GD库支持:²输出之前是否有任何的输出(尤其是UTF8的B ...
- Source tree配置gitlab
1.打开控制台:ssh-keygen -t rsa -C "GIT上的账号邮箱" 2.回车 3.输入密码(git上的账号密码) 4.确认密码 5.输入命令 cd .ssh 6.输入 ...