python测试驱动开发_使用Python进行测试驱动开发的简单介绍
python測試驅(qū)動開發(fā)
by Dmitry Rastorguev
德米特里·拉斯托格夫(Dmitry Rastorguev)
使用Python進行測試驅(qū)動開發(fā)的簡單介紹 (A simple introduction to Test Driven Development with Python)
I am a self-taught beginning developer who is able to write simple apps. But I have a confession to make. It’s impossible to remember how everything is interconnected in my head.
我是一位自學成才的開發(fā)人員,能夠編寫簡單的應用程序。 但是我要坦白。 不可能記住我腦子里所有事物是如何相互聯(lián)系的。
This situation is made worse if I come back to the code I’ve written after a few days. Turns out that this problem could be overcome by following a Test Driven Development (TDD) methodology.
如果幾天后回到我編寫的代碼,這種情況會變得更糟。 事實證明,遵循測試驅(qū)動開發(fā) (TDD)方法可以解決此問題。
什么是TDD?為什么重要? (What is TDD and why is it important?)
In layman’s terms, TDD recommends writing tests that would check the functionality of your code prior to your writing the actual code. Only when you are happy with your tests and the features it tests, do you begin to write the actual code in order to satisfy the conditions imposed by the test that would allow them to pass.
用外行的話來說,TDD建議編寫測試,以在編寫實際代碼之前檢查代碼的功能。 僅當您對測試及其測試的功能感到滿意時,才開始編寫實際的代碼,以滿足測試所施加的條件,使它們可以通過。
Following this process ensures that you careful plan the code you write in order to pass these tests. This also prevents the possibility of writing tests being postponed to a later date, as they might not be deemed as necessary compared to additional features that could be created during that time.
執(zhí)行此過程可確保您仔細計劃編寫的代碼,以通過這些測試。 這也避免了將編寫測試推遲到以后的可能性,因為與在此期間可能創(chuàng)建的其他功能相比,這些測試可能被認為不是必需的。
Tests also give you confidence when you begin to refactor code, as you are more likely to catch bugs due to the instant feedback when tests are executed.
當您開始重構(gòu)代碼時,測試還使您充滿信心,因為執(zhí)行測試時會得到即時反饋,因此更有可能捕獲錯誤。
如何開始? (How to get started?)
To begin writing tests in Python we will use the unittest module that comes with Python. To do this we create a new file mytests.py, which will contain all our tests.
要開始使用Python編寫測試,我們將使用Python隨附的unittest 模塊 。 為此,我們創(chuàng)建一個新文件mytests.py ,其中將包含所有測試。
Let’s begin with the usual “hello world”:
讓我們從通常的“ hello world”開始:
import unittestfrom mycode import * class MyFirstTests(unittest.TestCase): def test_hello(self): self.assertEqual(hello_world(), 'hello world')Notice that we are importing helloworld() function from mycode file. In the file mycode.py we will initially just include the code below, which creates the function but doesn’t return anything at this stage:
注意,我們正在從mycode文件導入helloworld()函數(shù)。 在文件mycode.py我們最初將僅包含以下代碼,該代碼創(chuàng)建函數(shù)但在此階段不返回任何內(nèi)容:
def hello_world(): passRunning python mytests.py will generate the following output in the command line:
運行python mytests.py將在命令行中生成以下輸出:
F ==================================================================== FAIL: test_hello (__main__.MyFirstTests) -------------------------------------------------------------------- Traceback (most recent call last): File "mytests.py", line 7, in test_hello self.assertEqual(hello_world(), 'hello world') AssertionError: None != 'hello world' -------------------------------------------------------------------- Ran 1 test in 0.000s FAILED (failures=1)This clearly indicates that the test failed, which was expected. Fortunately, we have already written the tests, so we know that it will always be there to check this function, which gives us confidence in spotting potential bugs in the future.
這清楚表明測試失敗,這是預期的。 幸運的是,我們已經(jīng)編寫了測試,因此我們知道它將一直在這里檢查該功能,這使我們有信心在將來發(fā)現(xiàn)潛在的錯誤。
To ensure the code passes, lets change mycode.py to the following:
為了確保代碼能夠通過, mycode.py更改為以下內(nèi)容:
def hello_world(): return 'hello world'Running python mytests.py again we get the following output in the command line:
再次運行python mytests.py ,我們在命令行中獲得以下輸出:
. -------------------------------------------------------------------- Ran 1 test in 0.000s OKCongrats! You’ve have just written your first test. Let’s now move on to a slightly more difficult challenge. We’ll create a function that would allow us to create a custom numeric list comprehension in Python.
恭喜! 您剛剛編寫了第一個測試。 現(xiàn)在讓我們繼續(xù)面對一個稍微困難一點的挑戰(zhàn)。 我們將創(chuàng)建一個函數(shù),該函數(shù)將允許我們在Python中創(chuàng)建自定義數(shù)字列表理解 。
Let’s begin by writing a test for a function that would create a list of specific length.
讓我們從編寫針對將創(chuàng)建特定長度列表的函數(shù)的測試開始。
In the file mytests.py this would be a method test_custom_num_list:
在文件mytests.py這將是test_custom_num_list方法:
import unittestfrom mycode import * class MyFirstTests(unittest.TestCase): def test_hello(self): self.assertEqual(hello_world(), 'hello world') def test_custom_num_list(self): self.assertEqual(len(create_num_list(10)), 10)This would test that the function create_num_list returns a list of length 10. Let’s create function create_num_list in mycode.py:
這將測試函數(shù)create_num_list返回長度為10的列表。讓我們在mycode.py創(chuàng)建函數(shù)create_num_list :
def hello_world(): return 'hello world' def create_num_list(length): passRunning python mytests.py will generate the following output in the command line:
運行python mytests.py將在命令行中生成以下輸出:
E. ==================================================================== ERROR: test_custom_num_list (__main__.MyFirstTests) -------------------------------------------------------------------- Traceback (most recent call last): File "mytests.py", line 14, in test_custom_num_list self.assertEqual(len(create_num_list(10)), 10) TypeError: object of type 'NoneType' has no len() -------------------------------------------------------------------- Ran 2 tests in 0.000s FAILED (errors=1)This is as expected, so let’s go ahead and change function create_num_list in mytest.py in order to pass the test:
這是預期的,所以讓我們繼續(xù)并在mytest.py中更改函數(shù)create_num_list以便通過測試:
def hello_world(): return 'hello world' def create_num_list(length): return [x for x in range(length)]Executing python mytests.py on the command line demonstrates that the second test has also now passed:
在命令行上執(zhí)行python mytests.py演示了第二個測試現(xiàn)在也通過了:
.. -------------------------------------------------------------------- Ran 2 tests in 0.000s OKLet’s now create a custom function that would transform each value in the list like this: const * ( X ) ^ power . First let’s write the test for this, using method test_custom_func_ that would take value 3 as X, take it to the power of 3, and multiply by a constant of 2, resulting in the value 54:
現(xiàn)在讓我們創(chuàng)建一個自定義函數(shù),該函數(shù)將轉(zhuǎn)換列表中的每個值,如下所示: const * ( X ) ^ power 。 首先,讓我們使用方法test_custom_func_編寫測試,該方法將值3作為X,將其乘以3的冪,然后乘以2的常數(shù),得出值54:
import unittestfrom mycode import * class MyFirstTests(unittest.TestCase): def test_hello(self): self.assertEqual(hello_world(), 'hello world') def test_custom_num_list(self): self.assertEqual(len(create_num_list(10)), 10) def test_custom_func_x(self): self.assertEqual(custom_func_x(3,2,3), 54)Let’s create the function custom_func_x in the file mycode.py:
讓我們在mycode.py文件中創(chuàng)建函數(shù)custom_func_x :
def hello_world(): return 'hello world' def create_num_list(length): return [x for x in range(length)] def custom_func_x(x, const, power): passAs expected, we get a fail:
不出所料,我們失敗了:
F.. ==================================================================== FAIL: test_custom_func_x (__main__.MyFirstTests) -------------------------------------------------------------------- Traceback (most recent call last): File "mytests.py", line 17, in test_custom_func_x self.assertEqual(custom_func_x(3,2,3), 54) AssertionError: None != 54 -------------------------------------------------------------------- Ran 3 tests in 0.000s FAILED (failures=1)Updating function custom_func_x to pass the test, we have the following:
更新函數(shù)custom_func_x以通過測試,我們具有以下內(nèi)容:
def hello_world(): return 'hello world' def create_num_list(length): return [x for x in range(length)] def custom_func_x(x, const, power): return const * (x) ** powerRunning the tests again we get a pass:
再次運行測試,我們通過了:
... -------------------------------------------------------------------- Ran 3 tests in 0.000s OKFinally, let’s create a new function that would incorporate custom_func_x function into the list comprehension. As usual, let’s begin by writing the test. Note that just to be certain, we include two different cases:
最后,讓我們創(chuàng)建一個新函數(shù),它將custom_func_x函數(shù)合并到列表custom_func_x 。 和往常一樣,讓我們??開始編寫測試。 請注意,可以肯定的是,我們包括兩種不同的情況:
import unittestfrom mycode import * class MyFirstTests(unittest.TestCase): def test_hello(self): self.assertEqual(hello_world(), 'hello world') def test_custom_num_list(self): self.assertEqual(len(create_num_list(10)), 10) def test_custom_func_x(self): self.assertEqual(custom_func_x(3,2,3), 54) def test_custom_non_lin_num_list(self): self.assertEqual(custom_non_lin_num_list(5,2,3)[2], 16) self.assertEqual(custom_non_lin_num_list(5,3,2)[4], 48)Now let’s create the function custom_non_lin_num_list in mycode.py:
現(xiàn)在,讓我們創(chuàng)建函數(shù)custom_non_lin_num_list在mycode.py :
def hello_world(): return 'hello world' def create_num_list(length): return [x for x in range(length)] def custom_func_x(x, const, power): return const * (x) ** power def custom_non_lin_num_list(length, const, power): passAs before, we get a fail:
和以前一樣,我們失敗了:
.E.. ==================================================================== ERROR: test_custom_non_lin_num_list (__main__.MyFirstTests) -------------------------------------------------------------------- Traceback (most recent call last): File "mytests.py", line 20, in test_custom_non_lin_num_list self.assertEqual(custom_non_lin_num_list(5,2,3)[2], 16) TypeError: 'NoneType' object has no attribute '__getitem__' -------------------------------------------------------------------- Ran 4 tests in 0.000s FAILED (errors=1)In order to pass the test, let’s update the mycode.py file to the following:
為了通過測試,讓我們將mycode.py文件更新為以下內(nèi)容:
def hello_world(): return 'hello world' def create_num_list(length): return [x for x in range(length)] def custom_func_x(x, const, power): return const * (x) ** power def custom_non_lin_num_list(length, const, power): return [custom_func_x(x, const, power) for x in range(length)]Running the tests for the final time, we pass all of them!
在最后一次運行測試,我們都通過了所有測試!
.... -------------------------------------------------------------------- Ran 4 tests in 0.000s OKCongrats! This concludes this introduction to testing in Python. Make sure you check out the resources below for more information on testing in general.
恭喜! 到此結(jié)束了對Python測試的介紹。 確保檢查以下資源,以獲取有關(guān)常規(guī)測試的更多信息。
The code is available here on GitHub.
該代碼可在GitHub上找到 。
進一步學習的有用資源! (Useful resources for further learning!)
網(wǎng)絡(luò)資源 (Web resources)
Below are links to some of the libraries focusing on testing in Python
以下是一些庫的鏈接,這些庫專注于Python測試
25.3. unittest - Unit testing framework - Python 2.7.14 documentationThe Python unit testing framework, sometimes referred to as "PyUnit," is a Python language version of JUnit, by Kent…docs.python.orgpytest: helps you write better programs - pytest documentationThe framework makes it easy to write small tests, yet scales to support complex functional testing for applications and…docs.pytest.orgWelcome to Hypothesis! - Hypothesis 3.45.2 documentationIt works by generating random data matching your specification and checking that your guarantee still holds in that…h(huán)ypothesis.readthedocs.iounittest2 1.1.0 : Python Package IndexThe new features in unittest backported to Python 2.4+.pypi.python.org
25.3。 unittest-單元測試框架-Python 2.7.14文檔 Python單元測試框架(有時也稱為“ PyUnit”)是Kent的JUnit的Python語言版本 。docs.python.org pytest:可幫助您編寫更好的程序-pytest文檔 該框架使編寫小型測試變得容易,但可以擴展以支持應用程序和...的復雜功能測試 。docs.pytest.org 歡迎來到假設(shè)! -假設(shè)3.45.2文檔 它的工作原理是生成與您的規(guī)范匹配的隨機數(shù)據(jù),并檢查您的保證是否仍然適用于… hypothesis.readthedocs.io unittest2 1.1.0:Python包索引 unittest的新功能已反向移植到Python 2.4+。 pypi.python.org
YouTube視頻 (YouTube videos)
If you prefer not to read, I recommend watching the following videos on YouTube.
如果您不想閱讀,建議您在YouTube上觀看以下視頻。
翻譯自: https://www.freecodecamp.org/news/learning-to-test-with-python-997ace2d8abe/
python測試驅(qū)動開發(fā)
總結(jié)
以上是生活随笔為你收集整理的python测试驱动开发_使用Python进行测试驱动开发的简单介绍的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 视频超分修复,让重温经典影片有了新的可能
- 下一篇: 谷歌分析相关套件简介