![](https://i-blog.csdnimg.cn/blog_migrate/11ab61846568f7310c1fec6b75306fcd.jpeg)
aiohttp web服务器单元测试
官方代码:https://github.com/aio-libs/aiohttp/blob/master/tests/test_client_functional.py
安装插件
pip install pytest-aiohttp
后端+测试 文件 server.py
import pytest
from aiohttp import web
import aiohttp
import logging
import datetime
routes = web.RouteTableDef()
@routes.get('/')
async def hello(request):
return web.Response(text="Hello, world")
async def test_hello(test_client, loop):
app = web.Application()
app.router.add_get('/', hello)
client = await test_client(app)
resp = await client.get('/')
assert resp.status == 200
text = await resp.text()
assert 'Hello, world' in text
@routes.get('/a')
async def previous(request):
if request.method == 'POST':
request.app['value'] = (await request.post())['value']
return web.Response(body=b'thanks for the data')
return web.Response(
body='value: {}'.format(request.app['value']).encode('utf-8'))
@pytest.fixture
def cli(loop, test_client):
app = web.Application()
app.router.add_get('/a', previous)
app.router.add_post('/a', previous)
return loop.run_until_complete(test_client(app))
async def test_set_value(cli):
resp = await cli.post('/a', data={'value': 'foo'})
assert resp.status == 200
assert await resp.text() == 'thanks for the data'
assert cli.server.app['value'] == 'foo'
async def test_get_value(cli):
cli.server.app['value'] = 'bar'
resp = await cli.get('/a')
assert resp.status == 200
assert await resp.text() == 'value: bar'
app = web.Application() # 创建app,设置最大接收图片大小为2M
app.add_routes(routes) # 添加路由映射
if __name__ == '__main__':pytest server.py
pass
web.run_app(app, host='0.0.0.0', port=8080) # 启动app
logging.info('server close:%s' % datetime.datetime.now())
执行单元测试
pytest server.py
flask web服务器单元测试
安装pytest
pip install -U pytest
验证安装
py.test --version
后端文件server.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'hello'
@app.route('/login')
def login():
return 'login'
@app.route('/logout')
def logout():
return 'logout'
@app.errorhandler(404)
def page_not_found():
return '404'
if __name__ == '__main__':
app.run()
测试文件test_params.py
import sys
import os
import unittest
dir_common = os.path.split(os.path.realpath(__file__))[0] + '/../'
sys.path.append(dir_common) # 将根目录添加到系统目录,才能正常引用common文件夹
# 引入后端代码文件
from server import app
class TestMathFunc(unittest.TestCase):
@classmethod
def setUpClass(cls):
"""测试开始时候执行, 用来做准备工作,一般用来初始化资源。"""
app.config['TESTING'] = True # 这将会使得处理请求时的错误捕捉失效,以便于 您在进行对应用发出请求的测试时获得更好的错误反馈。
# 测试客户端将会给我们一个通向应用的简单接口,我们可以激发 对向应用发送请求的测试,并且此客户端也会帮我们记录 Cookie 的 动态。
cls.app = app.test_client()
def teardown_class(self):
"""测试结束时执行, 用来做收尾工作, 一般用来关闭资源"""
pass
def test_login(self):
response = self.app.get('/login')
assert b'login' == response.data
def test_logout(self):
response = self.app.get('logout')
print(response)
assert b'logout' == response.data
def test_index(self):
response = self.app.get('/')
assert b'hello' == response.data
# 执行 pytest test.py
# 环境需要pip install -U pytest
if __name__ == '__main__':
unittest.main(verbosity=2)
运行:
pytest -q test_params.py
执行测试时需要下面几步:
- 从命令行进入测试文件所在目录,pytest会在该目录中寻找以test开头的文件
- 测试类以Test开头,并且不能带有
__init__
方法 - 找到测试文件,进入测试文件中寻找以test_开头的函数并执行
- 测试函数以断言assert结尾
覆盖率测试
安装
pip install coverage
在代码文件目录,例如后端文件server.py,测试文件test.py
执行代码覆盖率统计,只需要通过coverage的run参数执行被统计代码即可。
coverage run test.py arg1 arg2
test.py是测试脚本,arg1 arg2是test.py执行需要的参数。跑完后,会自动生成一个覆盖率统计结果文件(data file):.coverage。
注:coverage run test.py命令运行的文件,会统计项目中包括测试文件本身在内的所有文件,run参数的子参数—source
可以指定要统计的文件:$ coverage run --source=totest.py test.py
可以只统计totest.py文件。
有了覆盖率统计结果文件,只需要再运行report参数,就可以在命令里看到统计的结果。
coverage report -m test.py
Stmts/Miss表示语句总数/未执行到的语句数
Cover=(Stmts-Miss)/Stmts
生成html的测试报告。
coverage html test.py -d covhtml
生成的报告直接关联代码,高亮显示覆盖和未覆盖的代码,支持排序。-d指定html文件夹。
打开html统计结果
高亮显示覆盖的和未覆盖的代码,覆盖的用绿色标示,未覆盖的用红色标示。
web后端单元测试覆盖率
api形式调用coverage