写在前面的话:
作者是一名终身学习者,横跨环境、教育和IT三个行业。
IT是当前正在精进的行业,作者相信专业精神,崇尚知行合一。
作者以这个系列文章向每一个脚踏实地的web开发者致敬,希望能写出高度实用又有深度的文章帮路上的你清除障碍,欢迎你的指正和技术交流。
1.Test Framework
所有的代码都会出问题,这是编程的基础。以此出发,TDD--test driven development备受推崇,即使做不到,也很少有人会质疑测试的重要性。
一般认为测试从基础到集成分为unit test, integration test, system test, functional test, subcutaneous test。
- unit test: check a small bit of code, like a function or a class, in isolation of the rest of the system;
- integration test: check a larger bit of the code, maybe several classes, or a subsystem;
- system test(end-to-end): check all of the system under test in an environment as close to the end-user environment as possible;
- functional test: check a single bit of functionality of a system;
- subcutaneous test: a test that doesn’t run against the final end-user interface, but against an interface just below the surface. (like API layer)
一般developer要负责unit test,QA要负责functional test和subcutaneous test,其他测试根据实际情况分配。
当前很多团队都使用agile开发模式,但很多企业对agile的理解往往有偏差,有时候甚至是外行领导内行。断章取义的只强调功能的快速开发,以为agile相对于传统的waterfall就在于灵活调整需求,快速开发功能。实际上agile没有黑魔法,该做的工作不可能被省略,他的效率主要是通过developer与其他相关人员解耦合来释放工作能力的。
无论什么样的开发,都应该由测试来保障质量,软件工程在这一点上和传统工程不应该有差别。
2.Unit test
确认了测试的重要性,就要针对上一节的代码进行测试。一般认为unit test的工作量是代码编写的2-3倍,在开发估时的时候要做好相应的准备。
tests在逻辑上是和项目代码并列的,所以在根目录创建tests路径,在其中再创建unit tests路径,在unit tests针对index接口写unit test。
- FlaskTemplate
- tests
- unit_tests
- __init__.py
- test_index.py
- __init__.py
- venv
- .gitignore # 非git版本管理文件
- core.py
- README.md # 创建git仓库时选择生成的说明文档
接着安装测试工具pytest
$ pip install pytest
编写unit test代码
# -*- coding: utf8 -*-
# 引入待测试的代码
from core import index
def test_index_success():
"""
test index, response successfully
:return:
"""
response = index() # response接受index()的返回结果
assert response == "<h1>This is an index page.<h1/>" # 测试返回内容与预期返回内容相等
运行单元测试
$ pytest tests/unit_tests/test_index.py
============================ test session starts =============================
platform darwin -- Python 3.6.4, pytest-4.0.2, py-1.7.0, pluggy-0.8.0
rootdir: /Users/hongfu/Work/Computer_science/FlaskTemplate, inifile:
collected 1 item
tests/unit_tests/test_index.py . [100%]
========================== 1 passed in 0.24 seconds ==========================
3.Test Coverage
往往单元测试并不能完美覆盖,一方面是开发和测试的不同步造成的,另一方面有时也要放弃较安全代码的测试以换取更快的开发迭代,这时需要用测试覆盖率来反应代码测试的情况。
安装测试覆盖率工具coverage,pytest-cov
$ pip install coverage
$ pip install pytest-cov
将core.py放入根路径server中,以更好的管理项目结构
- FlaskTemplate
- server
- __init__.py
- core.py
- tests
- unit_tests
- __init__.py
- test_index.py
- __init__.py
- venv
- .gitignore # 非git版本管理文件
- README.md # 创建git仓库时选择生成的说明文档
运行测试覆盖率
$ pytest --cov=server # 用pytest测试server的代码覆盖率
========================================================================== test session starts ===========================================================================
platform darwin -- Python 3.6.4, pytest-4.0.2, py-1.7.0, pluggy-0.8.0
rootdir: /Users/hongfu/Work/Computer_science/FlaskTemplate, inifile:
plugins: cov-2.6.0
collected 1 item
tests/unit_tests/test_index.py . [100%]
---------- coverage: platform darwin, python 3.6.4-final-0 -----------
Name Stmts Miss Cover
----------------------------------------
server/__init__.py 0 0 100%
server/core.py 6 1 83%
----------------------------------------
TOTAL 6 1 83%
======================================================================== 1 passed in 0.33 seconds ========================================================================
4.Circle CI
后续的开发虽然会更加复杂,但底层逻辑和流程和这两节的过程是一致的:功能开发-unit test开发-test coverage报告。
在团队开发中,为了提高效率,往往使用自动化测试来提交代码,保证代码质量,降低代码审核的压力。所以CI(continuous integration)被大家普遍接受。
该项目在github上,其他平台的项目也同样可以使用CI管理。github的CI工具包括Hound, WIP, CircleCI等。
这里使用免费的CircleCI,在根路径创建.circleci路径并在其中创建config.yml
- FlaskTemplate
- .circleci
- config.yml
- server
- __init__.py
- core.py
- tests
- unit_tests
- __init__.py
- test_index.py
- __init__.py
- venv
- .gitignore # 非git版本管理文件
- README.md # 创建git仓库时选择生成的说明文档
version: 2
jobs:
build:
docker:
- image: circleci/python:3.6
steps:
- checkout
- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements.txt" }}
- run:
command: |
python3 -m venv venv
. venv/bin/activate
pip install -r requirements.txt
- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements.txt" }}
paths:
- "venv"
- run:
name: Running tests
command: |
. venv/bin/activate
pytest --cov=server
- store_artifacts:
path: test-reports/
destination: python_app
生成安装文件列表
$ pip freeze > requirements.txt
将相应代码提交到github,然后在circleCI使用github账号注册一个账号,选择ADD PROJECTS,在项目列表中选择FlaskTemplate,并点击SetupProject。
因为已经配置好circleCi,所跳过中间4步,直接点击Start Building,CI连接成功并测试通过。
5.CircleCI Test
接下来修改README,测试配置是否生效。
$ git checkout -b readme # 切换到新的reademe分支
修改readme文件
# FlaskTemplate
CI is applied using CircleCI.
提交readme分支
$ git add .
$ git commit -m "update readme"
$ git push origin readme
接着在github上提交一个pull request,点击下图右下角的compare & pull request。
然后通过pull request。
再检查circleCI,发现两条新的检查,一条是readme的检查,另一条是merge到master的检查。
至此,CI配置成功。