单元测试与 pytest
unittest Vs pytest
在单元测试中,我可以在 class 中设置变量,然后这个 class 的方法可以选择它想要使用的任何变量...
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
所以在 unittest 中,很容易将一堆测试放在一个 class 下,然后为不同的方法使用许多不同的变量(varA 和 varB)。在 pytest 中,我在 conftest.py 中创建了一个夹具,而不是在 unittest 中创建了 class,就像这样...
@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
我将此 input1 和 input2 提供给我在不同文件中的函数(比方说 test_this.py),用于两个不同的函数。以下是根据以上信息提出的问题...
因为我不能只在 conftest.py 中声明局部变量,因为我不能简单地导入这个文件。有没有更好的方法在这里声明可以在 test_this.py 中的不同函数中使用的不同变量?我在对这些变量的实际测试中有五种不同的配置,在 conftest.py 中定义了许多不同的固定装置并将它们用作 test_this.py 中五个不同函数的函数参数听起来很痛苦,我宁愿回到单元测试class 结构,定义我的变量,挑选我想要的
我是否应该只在 test_this.py 中声明全局变量并按我想要的方式在函数中使用它们?似乎有点不pythonic。此变量仅供此文件中的函数使用。
假设我还有 test_that.py 和 test_them.py。如果我在这些不同的文件之间有一些共享变量,我将如何声明它们?只需在所有这些测试文件所在的目录中创建一个文件 calle variables.py 并在需要时进行导入?这样我就可以将所有数据单独保存。
我的印象是 pytest 不鼓励使用 class 来组织函数吗?我在网上阅读的每个示例,似乎都只使用了一堆带有固定装置的功能。在pytest中定义class和方法并组织测试的配置是什么?
我有一个测试场景,我必须将一个函数的结果用于另一个函数。使用 pytest,我有一个位于函数末尾的断言,而不是 return,因此我无法将此函数用作固定装置。我该如何做到这一点?我知道这不是一个好习惯,因为我的一个测试依赖于另一个测试,但是有解决办法吗?
提前感谢您的回答。
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
或者您可以在单独的灯具中定义单独的变量:
def fixture_a():
return varA
def fixture_b():
return varB
def fixture_c():
return varC
def fixture_mod_A():
return modified_varA
或者制作一个夹具,其中 returns 所有变量(为什么不呢?)
甚至根据您的选择制作间接参数化夹具 returns 变量(非常令人困惑的方式):
@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
...
或者您甚至可以制作 fixture factory,它会即时为您制作 fixture。当您只有 5 个测试和 5 个变量配置时听起来很奇怪,但是当您同时获得数百个时,它会很有用。
3) 当然可以。但是我建议你不要直接导入这个文件,而是使用命令行选项指定要导入的文件。在这种情况下,您可以在不更改代码的情况下选择另一个带有变量的文件。
4) 我在测试中使用 类 因为我是从 nosetest 迁移过来的。我没有提到在 pytest 中使用 类 有任何问题。
5) 在这种情况下,我建议您执行以下操作:
拳头使功能具有所需的操作:
def some_actions(a, b):
# some actions here
...
return c
然后在测试和夹具中使用它:
def test():
assert some_actions(1,2) == 10
@pytest.fixture()
def some_fixture():
return some_actions(1,2)
我认为单元测试更容易阅读。对于测试新手来说,unittest 真的很简单。它开箱即用。您依赖 Python 实现,但未来几年它们不会更改界面。
我喜欢以每个文件最多有 1 个测试的方式组织我的测试。在那种情况下,我不依赖 类... 但我从每个测试中导入 类 来做事情。
一些网站抱怨单元测试中的颜色是不可能的。我认为这是一个笑话,因为我的单元测试为 Jenkins 和其他人创建了 JUNIT 输出报告。有很棒的工具(甚至 1 个文件)可以将 JUNIT 转换为网站,这不是测试工具的责任。
另外,有些人抱怨您需要大量代码才能开始单元测试。我不同意,创建一个单元测试需要 4 行代码!但是 Pytest 需要知道所有困难的注释,这对于一个简单的 Python 开发人员来说是不正常的。
一个重要的原因是 unittest 将保持免费。但是,如果您出于某种原因(bitbucket 等)想要使用 pytest,可以使用一些工具来转换您的测试并降低代码的可读性。
玩得开心!
在单元测试中,我可以在 class 中设置变量,然后这个 class 的方法可以选择它想要使用的任何变量...
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
所以在 unittest 中,很容易将一堆测试放在一个 class 下,然后为不同的方法使用许多不同的变量(varA 和 varB)。在 pytest 中,我在 conftest.py 中创建了一个夹具,而不是在 unittest 中创建了 class,就像这样...
@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
我将此 input1 和 input2 提供给我在不同文件中的函数(比方说 test_this.py),用于两个不同的函数。以下是根据以上信息提出的问题...
因为我不能只在 conftest.py 中声明局部变量,因为我不能简单地导入这个文件。有没有更好的方法在这里声明可以在 test_this.py 中的不同函数中使用的不同变量?我在对这些变量的实际测试中有五种不同的配置,在 conftest.py 中定义了许多不同的固定装置并将它们用作 test_this.py 中五个不同函数的函数参数听起来很痛苦,我宁愿回到单元测试class 结构,定义我的变量,挑选我想要的
我是否应该只在 test_this.py 中声明全局变量并按我想要的方式在函数中使用它们?似乎有点不pythonic。此变量仅供此文件中的函数使用。
假设我还有 test_that.py 和 test_them.py。如果我在这些不同的文件之间有一些共享变量,我将如何声明它们?只需在所有这些测试文件所在的目录中创建一个文件 calle variables.py 并在需要时进行导入?这样我就可以将所有数据单独保存。
我的印象是 pytest 不鼓励使用 class 来组织函数吗?我在网上阅读的每个示例,似乎都只使用了一堆带有固定装置的功能。在pytest中定义class和方法并组织测试的配置是什么?
我有一个测试场景,我必须将一个函数的结果用于另一个函数。使用 pytest,我有一个位于函数末尾的断言,而不是 return,因此我无法将此函数用作固定装置。我该如何做到这一点?我知道这不是一个好习惯,因为我的一个测试依赖于另一个测试,但是有解决办法吗?
提前感谢您的回答。
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
或者您可以在单独的灯具中定义单独的变量:
def fixture_a():
return varA
def fixture_b():
return varB
def fixture_c():
return varC
def fixture_mod_A():
return modified_varA
或者制作一个夹具,其中 returns 所有变量(为什么不呢?) 甚至根据您的选择制作间接参数化夹具 returns 变量(非常令人困惑的方式):
@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
...
或者您甚至可以制作 fixture factory,它会即时为您制作 fixture。当您只有 5 个测试和 5 个变量配置时听起来很奇怪,但是当您同时获得数百个时,它会很有用。
3) 当然可以。但是我建议你不要直接导入这个文件,而是使用命令行选项指定要导入的文件。在这种情况下,您可以在不更改代码的情况下选择另一个带有变量的文件。
4) 我在测试中使用 类 因为我是从 nosetest 迁移过来的。我没有提到在 pytest 中使用 类 有任何问题。
5) 在这种情况下,我建议您执行以下操作: 拳头使功能具有所需的操作:
def some_actions(a, b):
# some actions here
...
return c
然后在测试和夹具中使用它:
def test():
assert some_actions(1,2) == 10
@pytest.fixture()
def some_fixture():
return some_actions(1,2)
我认为单元测试更容易阅读。对于测试新手来说,unittest 真的很简单。它开箱即用。您依赖 Python 实现,但未来几年它们不会更改界面。
我喜欢以每个文件最多有 1 个测试的方式组织我的测试。在那种情况下,我不依赖 类... 但我从每个测试中导入 类 来做事情。
一些网站抱怨单元测试中的颜色是不可能的。我认为这是一个笑话,因为我的单元测试为 Jenkins 和其他人创建了 JUNIT 输出报告。有很棒的工具(甚至 1 个文件)可以将 JUNIT 转换为网站,这不是测试工具的责任。
另外,有些人抱怨您需要大量代码才能开始单元测试。我不同意,创建一个单元测试需要 4 行代码!但是 Pytest 需要知道所有困难的注释,这对于一个简单的 Python 开发人员来说是不正常的。
一个重要的原因是 unittest 将保持免费。但是,如果您出于某种原因(bitbucket 等)想要使用 pytest,可以使用一些工具来转换您的测试并降低代码的可读性。
玩得开心!