轉載鏈接:https://blog.csdn.net/qq_41963758/article/details/80366507
收起
Python unittest 理論上是不建議參數驅動的,其用例應該專注單元測試,確保每個method的邏輯正確。
引用Stack Overflow的一個答案,
“單元測試應該是獨立的,沒有依賴項的。這確保了每個用例都有非常具體而專一的測試反應。傳入參數會破壞單元測試的這個屬性,從而使它們在某種意義上無效。使用測試配置是最簡單的方法,也是更合適的方法,因爲單元測試不應該依賴外部信息來執行測試。那應該集成測試要做的。”
但是實際操作過程中,時不時還是有控制入參的需求的。比如,我想簡單實現一個web功能的cross-browser測試……
下面列出一些學習到的解決方案 (ENV: WIN 10, python36)。
利用類的屬性
這種方法可以不依賴其他第三方庫,而且可以將參數化應用到setUpClass 和setUp方法中。
即可以順利解決一個web 測試腳本cross-browser的驗證的問題。
class TestOdd1(unittest.TestCase):
NUMBER=1
def runTest(self):
"""Assert that the item is odd"""
self.assertTrue( self.NUMBER % 2 == 1, "Number should be odd")
class TestOdd2(TestOdd1):
NUMBER=2
if __name__ == '__main__':
unittest.main()
nose + ddt
用nose和ddt可以簡單的完成參數控制的test case,實際應用的是python的裝飾器(decorator)。
寫出來有些類似cucumber gherkin當中的scenario outline。
在實驗中,這個方法不適用於setUpClass。
pip install nose
pip install ddt
import unittest
from ddt import ddt, data
@ddt
class TestOdd(unittest.TestCase):
@data(3, 4, 12, 23)
def runTest(self, value):
self.assertTrue( self.NUMBER % 2 == 1, "Number should be odd")
執行 nosetests my_test.py ,4個test case被執行。
這個方案還支持從外部文件中加載參數。具體可以參考DDT 官方文檔。
重寫unittest.TestCase的__init__()
出處:Eli Bendersky的博客
定義類ParametrizedTestCase,使之集成unittest.TestCase並重寫其__init__(),增加param這個參數。
import unittest
class ParametrizedTestCase(unittest.TestCase):
""" TestCase classes that want to be parametrized should
inherit from this class.
"""
def __init__(self, methodName='runTest', param=None):
super(ParametrizedTestCase, self).__init__(methodName)
self.param = param
@staticmethod
def parametrize(testcase_klass, param=None):
""" Create a suite containing all tests taken from the given
subclass, passing them the parameter 'param'.
"""
testloader = unittest.TestLoader()
testnames = testloader.getTestCaseNames(testcase_klass)
suite = unittest.TestSuite()
for name in testnames:
suite.addTest(testcase_klass(name, param=param))
return suite
下面是一個包含我們用例的測試腳本,繼承了ParametrizedTestCase,
class TestOne(ParametrizedTestCase):
def test_something(self):
print 'param =', self.param
self.assertEqual(1, 1)
def test_something_else(self):
self.assertEqual(2, 2)
以參數驅動的方式執行用例
uite = unittest.TestSuite()
suite.addTest(ParametrizedTestCase.parametrize(TestOne, param=42))
suite.addTest(ParametrizedTestCase.parametrize(TestOne, param=13))
unittest.TextTestRunner(verbosity=2).run(suite)
將得到如下輸出,
test_something (__main__.TestOne) ... param = 42
ok
test_something_else (__main__.TestOne) ... ok
test_something (__main__.TestOne) ... param = 13
ok
test_something_else (__main__.TestOne) ... ok
----------------------------------------------------------------------
Ran 4 tests in 0.000s
OK
有同學私信討論說執行結果不符合預期,因私信有消息回覆限制。將內容更新到博客。
成文較早,我又重新嘗試了一下。以下是我的實驗結果。
目錄結構如下。
<test_dir>
| ---- test_temp.py
| ---- ParameterizedTestCase.py
ParameterizedTestCase.py文件裏是ParameterizedTestCase類和TestOne類。
test_temp.py內容如下:
import unittest
from scripts.ParameterizedTestCase import TestOne
if __name__ == '__main__':
suite = unittest.TestSuite()
suite.addTest(TestOne.parametrize(testcase_klass=TestOne, param=42))
suite.addTest(TestOne.parametrize(testcase_klass=TestOne, param=13))
unittest.TextTestRunner(verbosity=2).run(suite)
執行方式如下,而不是直接執行unittest。
summer@my-pc /d/my_test
$ export PYTHONPATH='/d/my_test'
summer@my-pc /d/my_test
$ python scripts/test_temp.py
test_something (scripts.ParameterizedTestCase.TestOne) ... ok
test_something_else (scripts.ParameterizedTestCase.TestOne) ... ok
test_something (scripts.ParameterizedTestCase.TestOne) ... ok
test_something_else (scripts.ParameterizedTestCase.TestOne) ... ok
----------------------------------------------------------------------
Ran 4 tests in 0.000s
OK
param = 42
param = 13
參考:
DDT官方文檔: http://ddt.readthedocs.io/en/latest/
https://technomilk.wordpress.com/2012/02/12/multiplying-python-unit-test-cases-with-different-sets-of-data/
https://eli.thegreenplace.net/2011/08/02/python-unit-testing-parametrized-test-cases/
————————————————
版權聲明:本文爲CSDN博主「SummerLaw」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_41963758/article/details/80366507