unittest vs pytest

Luc*_*arr 39 python unit-testing pytest

在unittest中,我可以在类中设置变量,然后这个类的方法可以选择它想要使用的任何变量......

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
Run Code Online (Sandbox Code Playgroud)

所以在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
Run Code Online (Sandbox Code Playgroud)

我将这个input1和input2作为两个不同的函数提供给我的函数在另一个文件中(比如说test_this.py).以下是基于以上信息的问题......

  1. 因为我不能在conftest.py中声明局部变量,因为我不能简单地导入这个文件.有没有更好的方法来声明不同的变量,可以在test_this.py中的不同函数中使用?我在实际测试这些变量时有五种不同的配置,在conftest.py中定义了许多不同的灯具,并在test_this.py的五个不同函数中使用它们作为函数参数听起来很痛苦,我宁愿回到unittest类结构,定义我的变量,挑选我想要的东西

  2. 我应该只在test_this.py中声明全局变量并按照我想要的方式在函数中使用它们吗?似乎有点不是pythonic.此变量仅由此文件中的函数使用.

  3. 假设我有test_that.py和test_them.py.如果我在这些不同的文件之间有一些共享变量,我将如何声明它们?只需在所有这些测试文件所在的目录中创建一个文件calle variables.py,并在需要时进行导入?这样我就可以将所有数据保持在一个单独的位置.

  4. 我的印象是pytest不鼓励使用类来组织你的功能吗?我在网上看到的每一个例子,似乎都只使用了一大堆功能.什么是定义类和方法的配置,并在pytest中组织测试?

  5. 我有一个测试场景,我必须将一个函数的结果用于另一个函数.使用pytest,我有一个断言,它位于函数的末尾而不是返回,所以我将无法将此函数用作夹具.我该如何做到这一点?我知道这不是一个好的做法,我的一个测试依赖于另一个,但是有一个解决方法吗?

提前感谢您的回答.

Ily*_*eev 31

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
Run Code Online (Sandbox Code Playgroud)

或者您可以在单独的灯具中定义单独的变量:

def fixture_a():
    return varA

def fixture_b():
    return varB

def fixture_c():
    return varC

def fixture_mod_A():
    return modified_varA
Run Code Online (Sandbox Code Playgroud)

或者制作一个返回所有变量的夹具(为什么不?),甚至制作间接参数化夹具,根据您的选择返回变量(非常混乱):

@pytest.fixture()
def parametrized_iput(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_iput', [('varA', 'varC')], indirect=True)
def test_1(parametrized_iput)
   varA, varC = parametrized_iput
   ...
Run Code Online (Sandbox Code Playgroud)

或者甚至你可以制作夹具工厂,它将为你动态制作灯具.当你只有5个测试和5个变量配置时,听起来很奇怪,但当你得到数百个变量时,它会很有用.

3)您可以使用cource.但我建议您不要直接导入此文件,而是使用命令行选项指向要导入的文件.在这种情况下,您可以在不更改代码的情况下使用变量共享另一个文件.

4)我在测试中使用类,因为我从nosetest迁移.我没有提到在pytest中使用类的任何问题.

5)在这种情况下,我建议你做以下事情:用所需的动作完成功能:

def some_actions(a, b):
    # some actions here
    ...
    return c
Run Code Online (Sandbox Code Playgroud)

然后在测试和夹具中使用它:

def test():
    assert some_actions(1,2) == 10

@pytest.fixture()
def some_fixture():
     return some_actions(1,2)
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这对我从 unittest 迁移到 py.test 有很大帮助。不过有一条评论:我认为应该使用 `@pytest.mark.usefixtures` 代替 `@pytest.usefixtures`。 (5认同)

Bar*_*ort 5

我认为unittest更容易阅读。对于新的测试人员,单元测试真的很容易。它开箱即用。您依赖于Python实现,但是它们不会在未来几年内更改接口。

我喜欢组织测试,每个文件最多可以进行1个测试。在那种情况下,我不依赖类...但是我从每个测试中导入类来做事情。

一些网站抱怨无法进行单元测试中的颜色。我认为这是个笑话,因为我的单元测试为Jenkins和其他人创建了JUNIT输出报告。有很多很棒的工具(甚至1个文件)都可以将JUNIT转换为网站,这不是测试工具的责任。

另外,有些人抱怨您需要大量代码才能开始单元测试。我不同意,创建一个单元测试需要4行代码!但是Pytest需要知道所有困难的注释,这对于简单的Python开发人员而言是不正常的。

一个重要的原因也是单元测试将保持免费。但是,如果出于某种原因(bitbucket等)想要使用pytest,则可以使用一些工具来转换测试并降低代码的可读性。

玩得开心!

  • “还有一个重要原因是,unittest 将保持免费。但是,如果您出于某种原因(bitbucket 等)想使用 pytest,可以使用一些工具来转换您的测试并降低代码的可读性。” 我不确定你在这里的意思,你是在暗示 pytest _won't_ 是免费的吗?另外,这里的“免费”是什么意思?最后一段让我很困惑 (21认同)
  • 我对unittest的唯一抱怨是他们使用像`self.assertEqual(some_var, 5)`这样的自定义语法操作,而不是pytest中干净的`assert some_var == 5` (10认同)
  • -1 为什么最后一条评论是“一个重要原因”——你的理由是什么?pytest 不是免费的吗?它与 bitbucket 有什么关系? (5认同)
  • 对于休闲开发人员或高级开发人员来说,unittest 并不比 pytest 更容易使用。您需要创建一个类,派生它,然后需要使用“self”来访问每个断言方法。使用 pytest,您只需创建一个函数,学习“assert”关键字就可以了。 (4认同)
  • “但是,如果您出于某种原因想使用 pytest(bitbucket 等)”,pytest 与 bitbucket 的集成比 unittest 更好吗? (2认同)
  • 最后一句“让代码可读性更差”削弱了这里的其他一些优点。标准库的一部分始终是使用包的一个很好的理由,并且单元测试可以在没有大量样板的情况下完成,但“可读”是非常主观的。 (2认同)
  • 感谢所有的评论。在撰写本文时,我担心 pytest 将来不会免费,但这是错误的想法。两个测试框架都是免费的,尽管用 pytest 编写会花费更多时间,而且我正在经营一家企业。 (2认同)