单元测试 python_Python单元测试简介

单元测试 python

You just finished writing a piece of code and you are wondering what to do. Will you submit a pull request and have your teammates review the code? Or will you manually test the code?

您刚刚编写了一段代码,并且想知道该怎么做。 您会提交拉取请求并让您的队友查看代码吗? 还是您将手动测试代码?

You should do both of these things, but with an additional step: you need to unit test your code to make sure that the code works as intended.

您应该同时完成这两项工作,但又需要执行额外的步骤:您需要对代码进行单元测试,以确保代码能够按预期工作。

Unit tests can pass or fail, and that makes them a great technique to check your code. In this tutorial, I will demonstrate how to write unit tests in Python and you'll see how easy it is to get them going in your own project.

单元测试可以通过或失败,这使它们成为检查代码的好技术。 在本教程中,我将演示如何用Python编写单元测试,并且您会发现将它们放入自己的项目中是多么容易。

入门 (Getting started)

The best way you can understand testing is if you do it hands-on. For that purpose, in a file named name_function.py, I will write a simple function that takes a first and last name, and returns a full name:

理解测试的最好方法是亲自进行测试。 为此,在名为name_function.py的文件中,我将编写一个简单的函数,该函数具有名字和姓氏,并返回全名:

#Generate a formatted full name
def formatted_name(first_name, last_name):
   full_name = first_name + ' ' + last_name
   return full_name.title()

The function formatted_name() takes the first and the last name and combines them with a space between to form a full name. It then capitalizes the first letter of every word. To check that this code works, you need to write some code that uses this function. In names.py I will write some simple code that lets users enter their first and last names:

函数formatted_name()接受名字和姓氏,并将其与空格之间组合起来以形成全名。 然后,将每个单词的首字母大写。 要检查此代码是否有效,您需要编写一些使用此功能的代码。 在names.py中,我将编写一些简单的代码,让用户输入名字和姓氏:

from name_function import formatted_name

print("Please enter the first and last names or enter x to E[x]it.")

while True:
   first_name = input("Please enter the first name: ")
   if first_name == "x":
       print("Good bye.")
       break

   last_name = input("Please enter the last name: ")
   if last_name == "x":
       print("Good bye.")
       break

   result = formatted_name(first_name, last_name)
   print("Formatted name is: " + result + ".")

This  code imports formatted_name() from name_function.py and on running, allows the user to enter a series of first and last names and shows the formatted full names.

该代码从name_function.py中导入formatted_name()并在运行时导入,允许用户输入一系列的名字和姓氏,并显示格式化的全名。

单元测试和测试用例 (Unit test and Test cases)

There is a module in Python’s standard library called unittest which contains tools for testing your code. Unit testing checks if all specific parts of your function’s behavior are correct, which will make integrating  them together with other parts much easier.

Python标准库中有一个名为unittest的模块,其中包含用于测试代码的工具。 单元测试检查功能行为的所有特定部分是否正确,这将使它们与其他部分的集成更加容易。

Test case is a collection of unit tests which together proves that a  function works as intended, inside a full range of situations in which that function may find itself and that it’s expected to handle. Test case should consider all possible kinds of input a function could receive from users, and therefore should include tests to represent each of these situations.

测试用例是单元测试的集合,这些测试一起证明该功能可以按预期工作,并且可以在该功能可能会发现自己并有望处理的所有情况下发挥作用。 测试用例应考虑功能可以从用户那里收到的所有可能的输入,因此,测试用例应包括代表每种情况的测试。

通过考试 (Passing a test)

Here’s a typical scenario for writing tests:

这是编写测试的典型方案:

First you need to create a test file. Then import the unittest module, define the testing class that inherits from unittest.TestCase, and lastly, write a series of methods to test all the cases of your function’s behavior.

首先,您需要创建一个测试文件。 然后导入unittest模块,定义从unittest.TestCase继承的测试类,最后​​编写一系列方法来测试函数行为的所有情况。

There’s a line by line explanation below the following code:

在以下代码下有逐行说明:

import unittest
from name_function import formatted_name

class NamesTestCase(unittest.TestCase):

   def test_first_last_name(self):
       result = formatted_name("pete", "seeger")
       self.assertEqual(result, "Pete Seeger")

First, you need to import a unittest and the function you want to test, formatted_name() . Then you create a class, for example NamesTestCase, that will contain tests for your formatted_name() function. This class inherits from the class unittest.TestCase.

首先,您需要导入一个单元测试和要测试的函数formatted_name()。 然后,创建一个类,例如NamesTestCase,它将包含对您的formatted_name()函数的测试。 该类继承自unittest.TestCase类。

NamesTestCase contains a single method that tests one part of formatted_name() . You  can call this method test_first_last_name().

NamesTestCase包含用于测试formatted_name()的一部分的单个方法。 您可以调用此方法test_first_last_name()。

Remember that every method that starts with “test_” will be run automatically when you run test_name_function.py.
请记住,当您运行test_name_function.py时,所有以“ test_”开头的方法都将自动运行。

Within test_first_last_name() test method, you call the function you want to test and store a return value. In this example we are going to call  formatted_name() with the arguments “pete” and “seeger” , and store the  result in the resulting variable.

在test_first_last_name()测试方法中,调用要测试的函数并存储返回值。 在此示例中,我们将使用参数“ pete”和“ seeger”调用formatted_name(),并将结果存储在结果变量中。

In the last line we will use the assert method. The assert method verifies that a result you received matches the result you expected to receive. And in this case we know that formatted_name() function will return full  name with capitalized first letters, so we expect the result “Pete  Seeger”. To check this, the unittest’s assertEqual() method is being  used.

在最后一行,我们将使用assert方法。 assert方法验证您收到的结果是否与预期收到的结果匹配。 在这种情况下,我们知道formatted_name()函数将返回全名,首字母大写,因此我们期望结果为“ Pete Seeger”。 为了检查这一点,使用了unittest的assertEqual()方法。

self.assertEqual(result, “Pete Seeger”)

This  line basically means: Compare the value in the resulting variable with “Pete Seeger” and if they are equal it’s OK, but if they are not let me know.

该行的基本含义是:将结果变量中的值与“ Pete Seeger”进行比较,如果它们相等,则可以,但是如果不告诉我。

On running test_name_function.py you are expected to get a OK meaning that the test has passed.

在运行test_name_function.py时,您将获得一个OK,表示测试已通过。

Ran 1 test in 0.001s

OK

测试失败 (Failing a test)

To show you what a failing test looks like I’m going to modify a  formatted_name() function by including a new middle name argument.

为了向您展示测试失败的样子,我将通过添加一个新的中间名参数来修改formatted_name()函数。

So I’m going to rewrite the function to look like this:

因此,我将重写该函数,使其看起来像这样:

#Generate a formatted full name including a middle name
def formatted_name(first_name, last_name, middle_name):
   full_name = first_name + ' ' + middle_name + ' ' + last_name
   return full_name.title()

This version of formatted_name() will work for people with middle names, but when you test it you will see that the function is broken for people who don’t have a middle name.

这个版本的formatted_name()适用于具有中间名的人,但是在测试它时,您会发现该功能对于没有中间名的人而言是无效的。

So when you run the test_name_function.py you will get the output that looks something like this:

因此,当您运行test_name_function.py时,您将获得如下所示的输出:

Error
Traceback (most recent call last):

File “test_name_function.py”, line 7, in test_first_last_name
    result = formatted_name(“pete”, “seeger”)

TypeError: formatted_name() missing 1 required positional argument: ‘middle_name’

Ran 1 test in 0.002s

FAILED (errors=1)

In the output you will see information that will tell you all you need to know where the test fails:

在输出中,您将看到信息,告诉您所有需要知道测试失败的地方:

  • First item in the output is the Error telling you that at least one test in test case resulted in an error.

    输出中的第一项是错误,它告诉您测试用例中至少有一个测试导致错误。
  • Next you’ll see the file and method in which the error occurred.

    接下来,您将看到发生错误的文件和方法。
  • After that you will see the line in which the error occurred.

    之后,您将看到发生错误的行。
  • And what kind of error it is, in this case we are missing 1 argument “middle_name”.

    这是什么错误,在这种情况下,我们缺少1个参数“ middle_name”。
  • You will also see the number of run tests, the time needed for the tests to  complete, and a textual message that represents the status of the tests with number of errors that occurred.

    您还将看到运行测试的数量,完成测试所需的时间以及一条文本消息,该文本消息表示测试的状态以及发生的错误数量。

测试失败时该怎么办 (What to do when the test has failed)

A passing test means the function is behaving according to what’s expected from it. However, a failing test means there’s more fun ahead of you.
通过测试意味着该功能正在按照预期的方式运行。 但是,失败的测试意味着您还有更多的乐趣。

I’ve seen couple of programmers that prefer to change the test instead of improving the code — but don’t to that. Spend a little more time to fix  the issue, as it will help you to better understand the code and save  time in the long run.

我见过一些程序员喜欢更改测试而不是改进代码,但是他们并不想这么做。 花更多的时间来解决此问题,因为从长远来看,它将帮助您更好地理解代码并节省时间。

In this example, our function formatted_name() first required two  parameters, and now as it is rewritten it requires one extra: a middle name. Adding a middle name to our function broke the desired behavior of  it. Since the idea is not to make changes to the tests, the best solution is to make middle name optional.

在此示例中,我们的函数formatted_name()首先需要两个参数,而现在在重写它时,它又需要一个额外的参数:中间名。 在我们的函数中添加中间名会破坏它的预期行为。 由于不打算更改测试,因此最好的解决方案是使中间名可选。

After we do this the idea is to make the tests pass when the first and last name are used, for example “Pete Seeger”, as well as when first, last and middle names are used, for example “Raymond Red Reddington”. So  let’s modify the code of formatted_name() once again:

完成此操作后,我们的想法是使测试在使用名字和姓氏(例如“ Pete Seeger”)以及使用名字,姓氏和中间名(例如“ Raymond Red Reddington”)时通过。 因此,让我们再次修改formatted_name()的代码:

#Generate a formatted full name including a middle name
def formatted_name(first_name, last_name, middle_name=''):
   if len(middle_name) > 0:
       full_name = first_name + ' ' + middle_name + ' ' + last_name
   else:
       full_name = first_name + ' ' + last_name
   return full_name.title()

Now the function should work for names with and without the middle name.

现在,该函数应该适用于带有或不带有中间名的名称。

And to make sure it still works with “Pete Seeger” run the test again:

为了确保它仍然可以与“ Pete Seeger”一起使用,请再次运行测试:

Ran 1 test in 0.001s

OK
And this is what I intended to show you: It’s always better to make changes to your code to fit your tests than other way around. Now the time has come to add a new test for names that do have a middle name.
这就是我想要向您显示的内容:更改代码以适合您的测试总是比其他方法更好。 现在该是为确实具有中间名称的名称添加新测试的时候了。

添加新测试 (Adding new tests)

Write a new method to the NamesTestCase class that will test for middle names:

将新方法写入NamesTestCase类,以测试中间名:

import unittest
from name_function import formatted_name

class NamesTestCase(unittest.TestCase):

    def test_first_last_name(self):
        result = formatted_name("pete", "seeger")
        self.assertEqual(result, "Pete Seeger")

    def test_first_last_middle_name(self):
        result = formatted_name("raymond", "reddington", "red")
        self.assertEqual(result, "Raymond Red Reddington")

After you run the test, both tests should pass:

运行测试后,两个测试都应通过:

Ran 2 tests in 0.001s

OK

Bra gjort!

胸罩gjort!

You have written your tests to check if the function works using names with  or without a middle name. Stay tuned for part 2 where I’ll talk more about testing in Python.

您已经编写了测试以检查该函数是否使用带有或不带有中间名的名称。 请继续关注第2部分,在该部分中,我将详细讨论Python测试。



Thank you for reading! Check out more articles like this on my freeCodeCamp profile: https://www.freecodecamp.org/news/author/goran/ and other fun stuff I build on my GitHub page: https://github.com/GoranAviani

感谢您的阅读! 在我的freeCodeCamp个人资料上查看更多类似的文章: https ://www.freecodecamp.org/news/author/goran/和我在GitHub页面上构建的其他有趣的东西: https : //github.com/GoranAviani

翻译自: https://www.freecodecamp.org/news/an-introduction-to-testing-in-python/

单元测试 python

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值