深入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 ...
随机推荐
- 【Android】SQLite基本用法(转)
在Android开发中SQLite起着很重要的作用,网上SQLite的教程有很多很多,不过那些教程大多数都讲得不是很全面.本人总结了一些SQLite的常用的方法,借着论坛的大赛,跟大家分享分享的.一. ...
- hdu 3579(中国剩余定理+考虑0)
Hello Kiki Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- 删除svn控制
1.用cmd 进去所要删除的目录 2.运行 for /r ./ %a in (./) do @if exist "%a/.svn" rd /s /q "%a/.svn& ...
- (21)python lambda表达式
lambda表达式是一个匿名函数 通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用 最简单的例子 add = lambda x,y : x + y print add(3,5) #out ...
- 《HelloGitHub》第 38 期
兴趣是最好的老师,HelloGitHub 就是帮你找到兴趣! 简介 分享 GitHub 上有趣.入门级的开源项目. 这是一个面向编程新手.热爱编程.对开源社区感兴趣 人群的月刊,月刊的内容包括:各种编 ...
- 10.1综合强化刷题 Day2 morning
一道图论神题(god) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有一张无向图G={V,E},这张无向图有n个点m条边组成.并且这是一张带权图,只有 ...
- eclipse启动Tomcat时报错:严重: Exception loading sessions from persistent storage
我的项目工程是Spring+hibernate+structs 1.0,最近启动tomcat时多次遇到如下异常: 严重: IOException while loading persisted se ...
- Ubuntu 16.04下使用Wine安装Notepad++
说明: 1.使用的Wine版本是深度出品(Deepin),已经精简了很多没用的配置,使启动能非常快,占用资源小. 2.关于没有.wine文件夹的解决方法:在命令行上运行winecfg: 下载: (链接 ...
- GCD和信号量
GCD 概念不多说,直接上代码.话说也不是什么高深的东东,不过极大简化了代码,一目了然.后面对信号量的记录也采用了相同的原理. //抛出线程 dispatch_async(dispatch_get_g ...
- 判断vps类型