Python 单元测试与 pytest
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27954702/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
unittest Vs pytest
提问by LuckyStarr
In unittest, I can setUp variables in a class and then the methods of this class can chose whichever variable it wants to use...
在单元测试中,我可以在一个类中设置变量,然后这个类的方法可以选择它想要使用的任何变量......
class test_class(unittest.TestCase):
def setUp(self):
self.varA = 1
self.varB = 2
self.varC = 3
self.modified_varA = 2
def test_1(self):
do_something_with_self.varA, self.varB
def test_2(self):
do_something_with_self_modified_varA, self.varC
So in unittest, it was easy to put bunch of tests together that could go under one class and then use many different variables (varA and varB) for different methods. In pytest, I created a fixture in conftest.py instead of a class in unittest, like this...
所以在 unittest 中,很容易将一堆测试放在一起,这些测试可以放在一个类下,然后对不同的方法使用许多不同的变量(varA 和 varB)。在pytest中,我在conftest.py中创建了一个fixture,而不是unittest中的一个类,就像这样......
@pytest.fixture(scope="module")
def input1():
varA = 1
varB = 2
return varA, varB
@pytest.fixture(scope="module")
def input2():
varA = 2
varC = 3
return varA, varC
I feed this input1 and input2 to my functions in a different file (let's say test_this.py) for two different functions. Here are the questions based on information above...
我将此 input1 和 input2 提供给不同文件(假设 test_this.py)中的函数,用于两个不同的函数。以下是基于以上信息的问题...
Since I can't just declare local variables in conftest.py as I can't simply import this file. Is there a better way of declaring different variables here that can be used in different functions in test_this.py ? I have five different configurations in my actual testing for these variables, defining that many different fixtures in conftest.py and use them as function argument in five different functions in test_this.py sounds painful, I would rather go back to unittest class structure, define my variables and pick and choose what I want
Should I just declare global variables in test_this.py and use them in the functions the way I want ? Seems a bit not pythonic. This variables are only used by the functions in this file.
Let's say I have test_that.py and test_them.py as well. If I have some shared variables between these different files, how would I declare them ? just create a file calle variables.py in the directory where all these test files are and do an import whenever I need ? This way I can keep all data in a separate.
Is it my impression that pytest discourages using a class to organize your functions ? Every example I read online, it all seem to employ bunch of functions with fixtures only. What is a configuration of defining class and methods and organize tests in pytest ?
I have a test scenario where I have to use result of one function into another. With pytest, I have an assert that is at the end of a function not a return so I won't be able to use this function as a fixture. How do I accomplish this ? I know this is not a good practice that my one test relies on another but is there a work around ?
因为我不能只在 conftest.py 中声明局部变量,因为我不能简单地导入这个文件。有没有更好的方法在这里声明可以在 test_this.py 中的不同函数中使用的不同变量?在我对这些变量的实际测试中,我有五种不同的配置,在 conftest.py 中定义了许多不同的装置并将它们用作 test_this.py 中五个不同函数中的函数参数听起来很痛苦,我宁愿回到 unittest 类结构,定义我的变量并挑选我想要的
我应该在 test_this.py 中声明全局变量并按照我想要的方式在函数中使用它们吗?似乎有点不是pythonic。此变量仅由此文件中的函数使用。
假设我也有 test_that.py 和 test_them.py。如果我在这些不同的文件之间有一些共享变量,我将如何声明它们?只需在所有这些测试文件所在的目录中创建一个文件 calle variables.py 并在需要时进行导入?这样我就可以将所有数据单独保存。
我的印象是 pytest 不鼓励使用类来组织您的函数吗?我在网上读到的每个例子,似乎都只使用了固定装置的一堆函数。在 pytest 中定义类和方法并组织测试的配置是什么?
我有一个测试场景,我必须将一个函数的结果用于另一个函数。使用 pytest,我在函数末尾有一个断言,而不是返回,因此我无法将此函数用作夹具。我如何做到这一点?我知道这不是一个好的做法,因为我的一个测试依赖于另一个测试,但有解决办法吗?
Thanks in advance for your answers.
预先感谢您的回答。
采纳答案by Ilya Karpeev
1) First of all, you can declare those fixtures not only in conftest.py, but in every Python module you want. And you can import that module. Also you can use fixtures in the same way as you used setUp method:
1) 首先,您不仅可以在 conftest.py 中声明这些装置,还可以在您想要的每个 Python 模块中声明这些装置。您可以导入该模块。您也可以以与使用 setUp 方法相同的方式使用设备:
@pytest.fixture(scope='class')
def input(request):
request.cls.varA = 1
request.cls.varB = 2
request.cls.varC = 3
request.cls.modified_varA = 2
@pytest.usefixtures('input')
class TestClass:
def test_1(self):
do_something_with_self.varA, self.varB
def test_2(self):
do_something_with_self_modified_varA, self.varC
or you can define separate variables in separate fixtures:
或者您可以在单独的装置中定义单独的变量:
def fixture_a():
return varA
def fixture_b():
return varB
def fixture_c():
return varC
def fixture_mod_A():
return modified_varA
or make one fixture which returns all the variables (why not?) or even make indirect parametrized fixture which returns variables by your choice (quite confusing way):
或者制作一个返回所有变量的夹具(为什么不呢?),或者甚至制作一个间接参数化的夹具,它可以根据您的选择返回变量(相当混乱的方式):
@pytest.fixture()
def parametrized_input(request):
vars = {'varA': 1, 'varB': 2, 'varC': 3}
var_names = request.param
return (vars[var_name] for var_name in var_names)
@pytest.mark.parametrize('parametrized_input', [('varA', 'varC')], indirect=True)
def test_1(parametrized_input)
varA, varC = parametrized_input
...
Or even you can make fixture factory which will make fixtures for you on the fly. Sounds curiously when you have only 5 tests and 5 configurations of variables, but when you get hundreds of both, it can be useful.
或者,您甚至可以制作固定装置工厂,它可以随时为您制作固定装置。当您只有 5 个测试和 5 个变量配置时,这听起来很奇怪,但是当您同时获得数百个变量时,它会很有用。
3) Of course you can. But I recommend you not to import this file directly, but use command line option pointing what file to import. In this case you can choose another file with variables without changing your code.
3)当然可以。但是我建议你不要直接导入这个文件,而是使用命令行选项来指定要导入的文件。在这种情况下,您可以在不更改代码的情况下选择另一个带有变量的文件。
4) I use classes in my tests because I migrated from nosetest. I didn't mention any problem with using classes in pytest.
4)我在测试中使用类,因为我是从鼻子测试迁移过来的。我没有提到在 pytest 中使用类的任何问题。
5) In that case I propose you to do the following: fist make the function with desired actions:
5)在这种情况下,我建议您执行以下操作:首先使用所需的操作制作功能:
def some_actions(a, b):
# some actions here
...
return c
then use it both in test and fixture:
然后在测试和夹具中使用它:
def test():
assert some_actions(1,2) == 10
@pytest.fixture()
def some_fixture():
return some_actions(1,2)
回答by Bart Mensfort
I think unittest is easier to read. For new testers, unittest is really easy. It is working out of the box. You depend on the Python implementation, but they will not change the interface coming years.
我认为 unittest 更容易阅读。对于新的测试人员来说,unittest 真的很容易。它是开箱即用的。您依赖于 Python 实现,但它们不会改变未来几年的界面。
I like to organize my tests in such a way that I have maximum 1 test per file. In that case I don't depend on classes... but I import classes from every test to do stuff.
我喜欢以每个文件最多 1 个测试的方式组织我的测试。在那种情况下,我不依赖于类……但我从每个测试中导入类来做事。
Some websites complain about colours in unittest is not possible. I think that is a joke, since my unittests create JUNIT output reports for Jenkins and others. There are great tools (even 1 file) to convert JUNIT to a website, that's not the responsibility of a test tool.
一些网站抱怨 unittest 中的颜色是不可能的。我认为这是个笑话,因为我的单元测试为 Jenkins 和其他人创建了 JUNIT 输出报告。有很棒的工具(甚至 1 个文件)可以将 JUNIT 转换为网站,这不是测试工具的责任。
Also, some people complain you need a lot of code to start a unittest. I disagree, it takes 4 lines of code to create a unittest! But Pytest needs to know all the difficult annotations, which are not normal for a simple Python developer.
此外,有些人抱怨您需要大量代码来启动单元测试。我不同意,创建单元测试需要 4 行代码!但是 Pytest 需要知道所有困难的注解,这对于一个简单的 Python 开发者来说是不正常的。
An important reasons also is that unittest will remain free. However, if you want to use pytest for some reason (bitbucket etc), there are tools to convert your tests and make the code less readable.
一个重要的原因也是 unittest 将保持免费。但是,如果您出于某种原因(bitbucket 等)想使用 pytest,则可以使用一些工具来转换您的测试并使代码的可读性降低。
Have fun!
玩得开心!

