前面说过,持续集成的边界,在开发到提交代码至代码仓库。而在提交代码之前,开发人员应该进行单元测试、语法检查等,因此我们需要使用Jenkins进行自动化的测试。
注:阅读本篇前应该先阅读上一篇:
一起DevOps系列28--实现项目持续集成&持续部署
No.0
前期准备
由于前面的testpythonapp,是直接使用了project根应用来测试的,并没有新建app,因此某些测试的地方容易引起歧义。为此,我们重新建一个project(名称为school),在里面使用如下命令,
djang-admin startapp schoolmgr
新建一个名为schoolmgr的应用。
No.1
python自动化测试包安装
在生产机器上面,进行对应的包安装。
pip install coveragepip install nose
No.2
手动单元测试
注意此时schoolmgr这个app的urls如下。
urlpatterns = [ url(r'^$', index,name="home"), url(r'^index/', index,name="index"), url(r'^temp/', temp,name="temp"),]
在school的工程根目录新建test.py文件,内容如下:
from django.core.urlresolvers import reversefrom django.urls import resolvefrom django.test import TestCasefrom schoolmgr.views import *class IndexTests(TestCase): def test_index_view_status_code(self): url = reverse('index') response = self.client.get(url) self.assertEquals(response.status_code, 200) def test_index_url_resolves_index_view(self): view = resolve('/index/') self.assertEquals(view.func, index)
everse函数的作用是,输入url_name,反向解析出url地址。上例,输入的url_name是index(即urls.py里面的name),用来找url,然后使用get函数访问url地址,查看页面返回代码是否正常(200为正常,404为找不到页面,403为没权限、500为内部错误等),从而确定网页是否能够正常访问。
resovle函数的作用是,输入url,解析出url_name或者对应的执行函数(view.func),后面输入views.py里面的函数名,对比view.func是否正确映射到预期的函数。
这里只是两个很简单的测试样例。
运行如下代码,就可以进行运行测试了,--verbosity参数用于控制测试过程中显示debug信息量,0是无输出,1是正常输出,2是详细输出。
python manage.py test --verbosity=2
返回结果
Ran 2 tests in 0.084sOKDestroying test database for alias 'default' (':memory:')...
表示测试成功。
No.3
手动检查测试样例代码覆盖率
测试前,template目录下面是有index.html与temp.html两个页面,并且views.py里面分别有两个页面的返回函数,urls.py也有两个页面的url解析记录。
def index(request): return render(request,'index.html')def temp(request): return render(request,'temp.html')
运行nosetests就可以查看,测试样例对代码的覆盖率了。(--cover-package后面填写的是app名称,不是project名称)
nosetests --with-coverage --with-xunit --cover-package=schoolmgr --cover-erase
然后就可以看到具体的覆盖情况了,会有报错。
Name Stmts Miss Cover-------------------------------------------schoolmgr\__init__.py 0 0 100%schoolmgr\views.py 5 2 60%-------------------------------------------TOTAL 5 2 60%----------------------------------------------------------------------Ran 0 tests in 0.446sFAILED (errors=1)----------------------------------------------------------------------ImproperlyConfigured: Requested setting DATABASES, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
按照提示的报错,网上找一下解决方案,修改一下test.py的代码,在代码最后开头增加如下内容。注意settings前面的是project name,不是app name。
import osimport djangoos.environ.setdefault("DJANGO_SETTINGS_MODULE", "school.settings") # project_name 项目名称django.setup()
重新执行,无报错。
Name Stmts Miss Cover-------------------------------------------schoolmgr\__init__.py 0 0 100%schoolmgr\admin.py 1 0 100%schoolmgr\models.py 1 0 100%schoolmgr\urls.py 6 0 100%schoolmgr\views.py 5 1 80%-------------------------------------------TOTAL 13 1 92%----------------------------------------------------------------------Ran 2 tests in 0.630sOK
可以看到,views.py里面只是覆盖了80%,并没有全覆盖,因为测试样例中,仅测试了index的页面,并没有测试temp的页面。
在test.py里面补充对temp页面的测试代码。
def test_temp_view_status_code(self): url = reverse('temp') response = self.client.get(url) self.assertEquals(response.status_code, 200)def test_temp_url_resolves_temp_view(self): view = resolve('/temp/') self.assertEquals(view.func, temp)
重新运行测试命令与覆盖率命令。
Name Stmts Miss Cover-------------------------------------------schoolmgr\__init__.py 0 0 100%schoolmgr\admin.py 1 0 100%schoolmgr\models.py 1 0 100%schoolmgr\urls.py 6 0 100%schoolmgr\views.py 5 0 100%-------------------------------------------TOTAL 13 0 100%----------------------------------------------------------------------Ran 4 tests in 0.634sOK
显示测试样例已经100%覆盖代码。
No.4
Linux系统安装agent
安装pylint
pip3 install pylint
然后运行如下命令,会自动检测语法书写得有问题的地方,并且提示。
pylint -f parseable mypackage/ | tee pylint.out
No.5
自动化测试
手动运行测试样例已经解决,我们还需要利用Jenkins实现每次提交代码到Git仓库的时候,自动化运行代码测试。
方法1(不推荐):在jenkins服务器需要在操作系统层面安装coverage,nose,pylint库。
方法2(不推荐):在jenkins安装目录下面的workspace/项目名称文件夹里面创建虚拟环境,在虚拟环境里面安装上述插件。
方法3(推荐):在jenkins安装目录下面的workspace创建虚拟环境,多个项目共用。在虚拟环境里面安装上述插件。
pip3 install coveragepip3 install nosepip3 install pylintpip3 install django==1.11.22
安装完毕后,可以输入如下命令检查是否已经存在以下命令
nosetestscoverage
也可以输入whereis查看命令的绝对路径,或者将命令加入环境变量。
whereis nosetestsnosetests: /usr/local/bin/nosetestswhereis coveragecoverage: /usr/bin/coverage /usr/local/bin/coveragewhereis pylintpylint: /usr/local/bin/pylint
然后在“构建”处,增加2个Excute Shell,分别输入如下命令。
/usr/local/bin/nosetests --with-coverage --with-xunit --cover-package=schoolmgr --cover-erase && /usr/local/bin/coverage xml || exit 0
以及
/usr/local/bin/pylint -f parseable schoolmgr/ | tee pylint.out deactivate
然后设置Post-build Actions,设定Jenkins展示测试与代码覆盖率报告。
运行构建后,jenkins将自动生成出对应的代码质量检测与测试样例覆盖报告。