使用nose 進行Python項目的自動化測試

1、爲何使用nose?

  1. 編寫測試更容易。nose能夠自動識別繼承於unittest.TestCase的測試單元,並執行測試,並且,nose也能夠測試非繼承於unittest.TestCase的測試單元。nose提供了豐富的API便於編寫測試代碼。
  2. 執行測試更容易。 只要遵循一些簡單的規則去組織你的類庫和測試代碼,nose是能夠自動識別單元測試的。執行測試是很是耗資源的,可是,一段第一個測試模塊被加載後,nose就開始執行測試。
  3. 創建測試環境更容易。 
  4. 作你想作的事情更容易。 nose擁有不少內置的插件幫助進行暑輸出抓取、錯誤查找、代碼覆蓋、文檔測試(doctest)等等。一樣,若是你不喜歡這些內置插件提供的功能或者這些插件不能知足你的項目結構,你能夠自定義開發插件來完成你想要作的事情。

     

2、基本使用

   安裝:pip install nosehtml

   腳本命令:python

            nosetests [options] [(optional) test files or directories]正則表達式

            除了使用命令行這種方式以外,還能夠在根目錄下放置配置文件,配置文件的類型爲.noserc或nose.cfg文件。配置文件都是標準的ini內容格式。例如:python3.x

[nosetests]
verbosity=3
with-doctest=1

3、擴展使用

    nose自動收集單元測試,收集它當前工做目錄下的源代碼文件、目錄以及包。任何的源代碼文件、目錄或者包只要匹配正則表達式,他們就會被自動收集。包的測試收集按照樹的層級級別一級一級進行,所以package.tests、package.sub.tests、package.sub.sub2.tests將會被收集。函數

   匹配成功的包、任何python的源文件都會當作測試用例。單元測試

   3.1 選擇測試用例

    將須要測試的名稱傳遞給nose的命令行。格式以下:測試

nosetests only_test_this.pyui

   測試的名稱能夠是腳本文件的名稱或者模塊的名稱,也可使用colon表達式表達的測試名稱。路徑能夠是相對的路徑也能夠是絕對的路徑。以下所示:this

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

    一樣可使用-w開關來切換當前的工做路徑,從而改變nose查找測試用例的根路徑。用法以下:spa

nosetests -w /path/to/tests

     更多關於自定義測試用例的收集與加載方式,可使用插件的方式作到。

 

3.2 配置

   除了3.1經過腳本命令傳遞參數的方式外,你還能夠在根目錄下經過設置setup.cfg或者.noserc或者nose.cfg等配置文件達到一樣的目的。例如:

[nosetests]
verbosity=3
with-doctest=1

  全部查找到的配置文件將會被加載,並且配置項的值會合並。若是想覆蓋標準的配置文件,使用-c選項。

3.3 使用插件

     使用pip安裝所須要的插件,而後經過nosetests命令行配置插件。執行以下命令驗證所安裝的插件,

nosetests –plugins

  在命令行中添加

-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、編寫測試用例

 

 

4.1 項目組織結構

    因爲nose是自動收集測試用例的,只有nose執行的測試目錄下的源代碼文件、包名、子目錄名跟正則表達式匹配成功後,才能被收集。並且代碼是樹級層次顯示的話,nose會逐級向下查找子目錄下的匹配的測試用例。

    匹配的正則表達式默認值爲:((?:^|[\\b_\\.-])[Tt]est.因此最好是以Test開頭,或者test開頭。固然也能夠修改默認的匹配的正則表達式。

  因此,推薦的項目結構爲:

image

 

   爲項目單獨建一個test包,裏面按項目模塊分子包,最後以及爲 「test_」開頭的測試用例源文件。

 

 

4.2  測試結果

image

   

 

 

4.3測試代碼

  test_mymath.py中的代碼以下:

# -*- 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))

 

test_logicOper.py 中的代碼以下:

# -*- 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)

   

 

 

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.

image

大致能夠得出以下結論:
1)測試的順序整體上按照包—>模塊—>類的順序進行;
2) 而後按照測試用例名稱的升序排序進行,好比test_math_multipy比test_math_square先執行;
3)當測試模塊中既包含測試函數,又包含測試類時,都必定是先執行setup(若是定義了),模塊測試執行完畢後執行teardown(若是定義了)。並且模塊的setup、setdown只執行一次。
4)測試類中的每一個測試方法執行前先執行setup(若是定義了),執行完畢後執行teardown(若是定義了)。並且每一個測試方法的執行過程都是如此,新的方法從新按setup—>執行方法—>teardown的順序執行。
 
 

 

(3)關於setup 、teardown

       package、module、class均可以設置setup、teardown。

      1)package的setup 、teardown的設置

         放在__init__.py文件中,在整個測試的運行期間只運行一次。

        setup函數的取名能夠是 setup, setup_package, setUp, setUpPackage中的一個。  

       teardown 函數取名能夠是teardown, teardown_package, tearDown or tearDownPackage中的一個。

 

   2) module的setup 、teardown的設置

       在整個測試的運行期間只運行一次。

       setup函數的取名能夠是 setup, setup_module, setUp or setUpModule中的一個。  

       teardown 函數取名能夠是teardown_module, or tearDownModule中的一個。

 

   3)class的setup 、teardown的設置

     每一個測試方法執行時都會調用。

     setup函數的取名能夠是setup_class, setupClass, setUpClass, setupAll ,setUpAll中的一個。  

     teardown 函數取名能夠是teardown_class, teardownClass, tearDownClass, teardownAll ,tearDownAll中的一個。

    測試類能夠繼承unittest.TestCase ,也能夠不繼承,nose都能識別。

    4)測試方法的setup、teardown

         能夠經過with_setup裝飾器進行設置,好比

image

 

總之,nose的口號是:nose extends unittest to make testing easier(測試更簡單).

相關文章
相關標籤/搜索