nose python test

一、为什么使用nose?

  1. 编写测试更容易。nose可以自动识别继承于unittest.TestCase的测试单元,并执行测试,而且,nose也可以测试非继承于unittest.TestCase的测试单元。nose提供了丰富的API便于编写测试代码。
  2. 执行测试更容易。 只要遵循一些简单的规则去组织你的类库和测试代码,nose是可以自动识别单元测试的。执行测试是非常耗资源的,但是,一段第一个测试模块被加载后,nose就开始执行测试。
  3. **建立测试环境更容易。 **
  4. 做你想做的事情更容易。 nose拥有很多内置的插件帮助进行暑输出抓取、错误查找、代码覆盖、文档测试(doctest)等等。同样,如果你不喜欢这些内置插件提供的功能或者这些插件不能满足你的项目结构,你可以自定义开发插件来完成你想要做的事情。

二、基本使用

安装:pip install nose

脚本命令:

        nosetests [options] [(optional) test files or directories]

        除了使用命令行这种方式之外,还可以在根目录下放置配置文件,配置文件的类型为.noserc或nose.cfg文件。配置文件都是标准的ini内容格式。例如:

<pre>[nosetests] verbosity=3 with-doctest=1</pre>

三、扩展使用

nose自动收集单元测试,收集它当前工作目录下的源代码文件、目录以及包。任何的源代码文件、目录或者包只要匹配正则表达式,他们就会被自动收集。包的测试收集按照树的层级级别一级一级进行,因此package.tests、package.sub.tests、package.sub.sub2.tests将会被收集。

匹配成功的包、任何python的源文件都会当做测试用例。

3.1 选择测试用例

将需要测试的名称传递给nose的命令行。格式如下:

nosetests only_test_this.py

测试的名称可以是脚本文件的名称或者模块的名称,也可以使用colon表达式表达的测试名称。路径可以是相对的路径也可以是绝对的路径。如下所示:

<pre>nosetests test.module
nosetests another.test:TestCase.test_method
nosetests a.test:TestCase
nosetests /path/to/test/file.py:test_function</pre>

同样可以使用-w开关来切换当前的工作路径,从而改变nose查找测试用例的根路径。用法如下:

nosetests -w /path/to/tests

 更多关于自定义测试用例的收集与加载方式,可以使用插件的方式做到。

3.2 配置

除了3.1通过脚本命令传递参数的方式外,你还可以在根目录下通过设置setup.cfg或者.noserc或者nose.cfg等配置文件达到同样的目的。例如:

<pre>[nosetests] verbosity=3 with-doctest=1</pre>

所有查找到的配置文件将会被加载,而且配置项的值会合并。如果想覆盖标准的配置文件,使用-c选项。

3.3 使用插件

 使用pip安装所需要的插件,然后通过nosetests命令行配置插件。执行如下命令验证所安装的插件,

nosetests –plugins

<pre> 在命令行中添加</pre>

-v或者-vv选项可以显示每一个插件的更多信息。 如果通过nose.main()或者nose.run()执行测试,可以将要使用的插件关键字参数的列表传递进去。

3.4 配置选项

-V,—version

输出nose的版本

-p,—plugins

输出可获取的插件列表。

-v=DEFUALT,—verbose=DEFAULT

使用更多的verbose

--verbosity=VERBOSITY

设置verbosity;--verbosity=2与-v设置一致

-q,—quiet=DEFAULT

使用更少的verbose

-c=FILES,—config=FILES

设置配置文件。可以设置很多次,然后将所有的配置文件合并。

-w=WHERE,--where=WHERE

设置查找的根目录。

-py3where=WHERE

顾名思义,针对python3.x以上设置查找路径。

-m=REGEX,--match=REGEX,—testmatch=REGEX

设置用于自动化收集用例的正则表达式。

--tests=NAMES

执行这些测试。

--debug-log=FILE

设置调试的日志文件路径。

--logging-config=FILE,—log-config=FILE

设置日志文件的配置文件。

-I=REGEX,—ignore-files=REGEX

设置自动收集测试用例时忽略的正则表达式。

-e=REGEX,—exclude=REGEX

排除要执行的测试用例的正则表达式

-i=REGEX,—include=REGEX

包含要执行的测试用例的正则表达式

-x,—stop

执行测试发生错误后,停止执行测试。

--noexe

不查找可以执行文件。

-a=ATTR,--attr=ATTR

只执行包含ATTR属性的测试用例。

-A=EXPR,—eval-attr=EXPR

只执行属性与EXPR匹配的测试用例。

-s,—nocapture

不抓取标准输出(stdout)

--nologcapture

禁止使用日志插件

--logging-format=FORMAT

打印语句的自定义格式

--logging-datefmt=FORMAT

日志的日期时间格式

--logging-filter=FILTER

日志语句的过滤器。

--logging-clear-handlers

清除日志的其他handlers

--logging-level=DEFUALT

设置日志的等级

--with-coverage

开启coverage插件

--cover-package=PACKAGE

限定coverage所在包

--cover-erase

在执行之前 清除上次coverage统计结果

--cover-testes

在coverage报告中包含测试模块

--cover-html

产生html的coverage报告

--cover-html-dir=DIR

设置存储html的目录

--cover-xml

产生xml的coverage报告

--cover-xml-file=FILE

设置存储coverage报告的xml文件

--cover-config-file=DEFUALT

设置coverage的配置文件

-pdb

当测试失败或产生错误是进入调试模式

--pdb-failures

当测试失败时进入调试模式

--pdb-errors

当测试产生错误时进入调试模式

--with-doctest

开启doctest插件

--doctest-tests

在测试模块中查询doctests

--with-profile

开启profile插件

--profile-sort=SORT

设置profiler 输出排序

--profile-stats-file=FILE

设置统计所在的文件地址

--with-id

开启TestId插件

--processes=NUM

开始测试处理器的个数

--processes-timeout=SECONDS

设置超时时间。

--with-xuint

开始Xunit插件

--xuint-file=FILE

设置XUnit报告所在的xml文件

--all-modules

开启AllModules插件

--collect-only

开启只收集测试功能。只收集测试用例及输出测试名字,而不执行测试

四、编写测试用例

4.1 项目组织结构

由于nose是自动收集测试用例的,只有nose执行的测试目录下的源代码文件、包名、子目录名跟正则表达式匹配成功后,才能被收集。而且代码是树级层次显示的话,nose会逐级向下查找子目录下的匹配的测试用例。

匹配的正则表达式默认值为:(`(?:^|[\\b_\\.-])[Tt]est.所以最好是以Test开头,或者test开头。当然也可以修改默认的匹配的正则表达式。`

所以,推荐的项目结构为:

[图片上传中...(image-cd293d-1556365810616-7)]

为项目单独建一个test包,里面按项目模块分子包,最后以及为 “test_”开头的测试用例源文件。

4.2 测试结果

[图片上传中...(image-5cfdf9-1556365810616-6)]

4.3测试代码

test_mymath.py中的代码如下:

[
复制代码

](javascript:void(0); "复制代码")

<pre># -- coding: utf-8 --
author = 'Administrator'
from nose.tools import assert_equal from nose.tools import with_setup import unittest import mymath.math as mmath def setUp(): print("============test math module setup==============") def teardown(): print("============test math module teardown==============") def test_math_add():
result=mmath.add(4, 5) print("================test_math_add============")
assert_equal(10, result) class test_math3(): def setUp(self): print("============test math class setup==============") def teardown(self): print("============test math class teardown==============") def test_math_square(self): print("=============== test_math_square================ ")
assert_equal(9, mmath.square(3)) def test_math_sub(self): print("=============== test_math_sub================ ")
assert_equal(1, mmath.sub(3, 2)) class test_math2(unittest.TestCase): def test_math_multipy(self): print("=============== test_math_multipy================ ")
assert_equal(8, mmath.multiply(2, 4))</pre>

[
复制代码

](javascript:void(0); "复制代码")

test_logicOper.py 中的代码如下:

[
复制代码

](javascript:void(0); "复制代码")

<pre># -- coding: utf-8 --
author = 'Administrator'

from nose.tools import assert_equal from logicOperator.localOperator import *
def test_logicOper_isGreaterThan(): print("=================test_logicOper_isGreaterThan============")
result=isGreaterThan(4,3)
assert_equal(True,result)</pre>

[
复制代码

](javascript:void(0); "复制代码")

4.4 测试分析

(1)测试用例的收集

 由于nose是按照正则表达式自动收集匹配的测试用例。我们这里收集了5个测试用例。分别了
  • test_mymath.py模块里的test_math_add函数。
  • test_mymath.py模块里的test_math3类下面的test_math_square、test_math_sub两个函数。
  • test_mymath.py模块里的test_math2类下面的test_math_multipy函数。
  • test_logicOper.py模块里的test_logicOper_isGreaterThan函数。

(2)测试的运行顺序。

从下图打印输出的结果可以看出。收集的测试用例的执行顺序test_logicOper_isGreaterThan—>test_mymath(模块).setup—>test_math2(类).test_math_multipy—>test_math3(类).setup—>test_math3(类).test_math_square—>

test_math3(类).teardown—>test_math3(类).setup—>test_math3(类).test_math_sub—>test_math3(类).teardown—>test_mymath(模块).test_math_add—>test_mymath(模块).teardown.

<pre>大体可以得出如下结论:</pre>

<pre>1)测试的顺序总体上按照包—>模块—>类的顺序进行;</pre>

<pre>2) 然后按照测试用例名称的升序排序进行,比如test_math_multipy比test_math_square先执行;</pre>

<pre>3)当测试模块中既包含测试函数,又包含测试类时,都一定是先执行setup(如果定义了),模块测试执行完毕后执行teardown(如果定义了)。而且模块的setup、setdown只执行一次。</pre>

<pre>4)测试类中的每个测试方法执行前先执行setup(如果定义了),执行完毕后执行teardown(如果定义了)。而且每个测试方法的执行过程都是如此,新的方法重新按setup—>执行方法—>teardown的顺序执行。</pre>

(3)关于setup 、teardown

   package、module、class都可以设置setup、teardown。

  1)package的setup 、teardown的设置

     放在__init__.py文件中,在整个测试的运行期间只运行一次。

    setup函数的取名可以是 <cite>setup</cite>, <cite>setup_package</cite>, <cite>setUp</cite>, <cite>setUpPackage**中的一个。  **</cite>

<cite> teardown 函数取名可以是t<cite>eardown</cite>, <cite>teardown_package</cite>, <cite>tearDown</cite> or <cite>tearDownPackage中的一个。</cite></cite>

2) module的setup 、teardown的设置

   在整个测试的运行期间只运行一次。

   setup函数的取名可以是 <cite><cite>setup</cite>, <cite>setup_module</cite>, <cite>setUp</cite> or <cite>setUpModule</cite></cite><cite>**中的一个。  **</cite>

<cite> teardown 函数取名可以是<cite>teardown_module</cite>, or <cite>tearDownModule</cite><cite>中的一个。</cite></cite>

3)class的setup 、teardown的设置

 每个测试方法执行时都会调用。

 setup函数的取名可以是<cite>setup_class</cite>, <cite>setupClass</cite>, <cite>setUpClass</cite>, <cite>setupAll</cite> ,<cite>setUpAll</cite><cite>**中的一个。  **</cite>

 teardown 函数取名可以是<cite>teardown_class</cite>, <cite>teardownClass</cite>, <cite>tearDownClass</cite>, <cite>teardownAll</cite> ,<cite>tearDownAll</cite><cite>中的一个。</cite>

<cite> 测试类可以继承unittest.TestCase ,也可以不继承,nose都能识别。</cite>

4)测试方法的setup、teardown

     可以通过with_setup装饰器进行设置,比如

[图片上传中...(image-fbc60d-1556365810615-4)]

总之,nose的口号是:nose extends unittest to make testing easier(测试更简单).

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容