单元测试 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_namereturn 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_nameprint("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.")breaklast_name = input("Please enter the last name: ")if last_name == "x":print("Good bye.")breakresult = 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_nameclass 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.001sOK

测试失败 (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_namereturn 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_nameresult = formatted_name(“pete”, “seeger”)TypeError: formatted_name() missing 1 required positional argument: ‘middle_name’Ran 1 test in 0.002sFAILED (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_nameelse:full_name = first_name + ' ' + last_namereturn 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.001sOK
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_nameclass 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.001sOK

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/391198.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

飞行模式的开启和关闭

2019独角兽企业重金招聘Python工程师标准>>> if(Settings.System.getString(getActivity().getContentResolver(),Settings.Global.AIRPLANE_MODE_ON).equals("0")) { Settings.System.putInt(getActivity().getContentResolver(),Settings.Global.AIRPLA…

消解原理推理_什么是推理统计中的Z检验及其工作原理?

消解原理推理I Feel:我觉得: The more you analyze the data the more enlightened, data engineer you will become.您对数据的分析越多,您将变得越发开明。 In data engineering, you will always find an instance where you need to establish whet…

pytest+allure测试框架搭建

https://blog.csdn.net/wust_lh/article/details/86685912 https://www.jianshu.com/p/9673b2aeb0d3 定制化展示数据 https://blog.csdn.net/qw943571775/article/details/99634577 环境说明: jdk 1.8 python 3.5.3 allure-commandline 2.13.0 文档及下载地址&…

lintcode433 岛屿的个数

岛屿的个数 给一个01矩阵,求不同的岛屿的个数。 0代表海,1代表岛,如果两个1相邻,那么这两个1属于同一个岛。我们只考虑上下左右为相邻。 您在真实的面试中是否遇到过这个题? Yes样例 在矩阵: [[1, 1, 0, …

大数据分析要学习什么_为什么要学习数据分析

大数据分析要学习什么The opportunity to leverage insights from data has never been greater.利用来自数据的洞察力的机会从未如此大。 Humans tend to generate a lot of data each day - from heart rates to favorite songs, fitness goals and movie preferences. You …

POJ - 3257 Cow Roller Coaster (背包)

题目大意:要用N种材料建一条长为L的路,如今给出每种材料的长度w。起始地点x。发费c和耐久度f 问:在预算为B的情况下,建好这条路的最大耐久度是多少 解题思路:背包问题 dp[i][j]表示起始地点为i。发费为j的最大耐久度…

leetcode 1473. 粉刷房子 III(dp)

在一个小城市里,有 m 个房子排成一排,你需要给每个房子涂上 n 种颜色之一(颜色编号为 1 到 n )。有的房子去年夏天已经涂过颜色了,所以这些房子不需要被重新涂色。 我们将连续相同颜色尽可能多的房子称为一个街区。&a…

大学生信息安全_给大学生的信息

大学生信息安全You’re an undergraduate. Either you’re graduating soon (like me) or you’re in the process of getting your first college degree. The process is not easy and I can only assume how difficult the pressures on Masters and Ph.D. students are. Ho…

打破冷漠僵局文章_保持冷静并打破僵局-最佳

打破冷漠僵局文章Hack The Box (HTB) is an online platform allowing you to test your penetration testing skills. It contains several challenges that are constantly updated. Some of them simulating real world scenarios and some of them leaning more towards a …

使用DOM Breakpoints找到修改属性的Javascript代码

使用Chrome开发者工具的DOM断点功能可以让您快速找到修改了某一个DOM元素的Javascript代码。 在Chrome开发者工具里,选中想要监控的DOM元素,点击右键,选择Break on->Attributes modifications: 之后在DOM Breakpoints的tab里能看到对应的断…

特斯拉最安全的车_特斯拉现在是最受欢迎的租车选择

特斯拉最安全的车Have you been curious to know which cars are most popular in US and what are their typical rental fares in various cities? As the head of Product and Data Science at an emerging technology start-up, Ving Rides, these were some of the quest…

leetcode 740. 删除并获得点数(dp)

给你一个整数数组 nums ,你可以对它进行一些操作。 每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除每个等于 nums[i] - 1 或 nums[i] 1 的元素。 开始你拥有 0 个点数。返回你能通过这些操作…

WebSocket入门

WebSocket前言  WebSocket是HTML5的重要特性,它实现了基于浏览器的远程socket,它使浏览器和服务器可以进行全双工通信,许多浏览器(Firefox、Google Chrome和Safari)都已对此做了支持。 在WebSocket出现之前&#xff…

安卓游戏开发推箱子_保持冷静并砍箱子-开发

安卓游戏开发推箱子Hack The Box (HTB) is an online platform allowing you to test your penetration testing skills. It contains several challenges that are constantly updated. Some of them simulating real world scenarios and some of them leaning more towards …

自定义TabLayout

本文为kotlin仿开眼视频Android客户端的后续补充内容,本篇为大家介绍如何对TabLayout进行定制使用,基于项目需求,本篇主要对部分功能进行了定制,如:指示器距离文字的距离、文字选中加粗、文字选中变大等 本文部分代码参…

ml dl el学习_DeepChem —在生命科学和化学信息学中使用ML和DL的框架

ml dl el学习Application of Machine Learning and Deep Learning for Drug Discovery, Genomics, Microsocopy and Quantum Chemistry can create radical impact and holds the potential to significantly accelerate the process of medical research and vaccine developm…

响应式网站设计_通过这个免费的四小时课程,掌握响应式网站设计

响应式网站设计This video tutorial from Kevin Powell teaches you to build responsive websites from scratch. 凯文鲍威尔(Kevin Powell)的这段视频教程教您从头开始构建响应式网站。 The course starts with explaining the core concepts needed to start thinking resp…

2017-2018-1 20179215《Linux内核原理与分析》第二周作业

20179215《Linux内核原理与分析》第二周作业 这一周主要了解了计算机是如何工作的,包括现在存储程序计算机的工作模型、X86汇编指令包括几种内存地址的寻址方式和push、pop、call、re等几个重要的汇编指令。主要分为两部分进行这周的学习总结。第一部分对学习内容进…

python:单例模式--使用__new__(cls)实现

单例模式:即一个类有且仅有一个实例。 那么通过python怎么实现一个类只能有一个实例呢。 class Earth:"""假如你是神,你可以创造地球"""print 欢迎来到地球# 生成一个地球 a Earth() print id(a)# 再生成一个地球 b Ear…

重学TCP协议(5) 自连接

1.自连接是什么 在发起连接时,TCP/IP的协议栈会先选择source IP和source port,在没有显示调用bind()的情况下,source IP由路由表确定,source port由TCP/IP协议栈从local port range中选取尚未使用的port。 如果destination IP正…