基于fixture

时间:2016-06-21 15:50:14

标签: python pytest python-decorators

让我说我在conftest.py文件中建立了一个pytest fixture,看起来像:

def live_fixture():
    # network access here...
    pass

我在许多测试函数中使用相同的fixture,比如test_spam.py有一些测试函数:

@pytest.mark.live
def test_one(live_fixture):
    assert 1


def test_one():
    assert 2 

@pytest.mark.live
def test_three(live_fixture):
    assert 3

我在第一个和第三个测试函数上使用@pytest.mark.live装饰,因为这两个测试都依赖于夹具live_fixture,它通过网络传出并完成任务。理由:我喜欢让我的测试的可靠子集离线传递,例如。

py.test -m "not live" test_spam.py --blockage

将可靠地传递(使用漂亮的pytest-blockage模块来强制执行无网络访问限制。)

但是在这里使用@pytest.mark.live的每个测试函数上写出live_fixture装饰是单调乏味且容易出错的。有没有办法让该夹具声明任何使用它的测试函数都应该自动应用@pytest.mark.live修饰,或者某种方式来检测内部文件test_spam.py test_one和{{1}使用test_three,因此应该有效地装饰live_fixture

2 个答案:

答案 0 :(得分:2)

我找到了另一个合理的解决方案,试图弄清楚pytest.mark是如何工作的。

我发现类Node有一个方法“add_marker”,它应该是实现功能pytest.mark的确切方法。并且类Item从Node扩展。

所以我的解决方案是:

  1. 试图找出测试是否使用了夹具。
  2. 让测试的Item对象调用add_marker
  3. 示例:在conftest.py中添加以下方法

      #validations      
        validates_uniqueness_of :bmp_id, :message => "TODO", if: :pad_and_pipes_exists
    
    
      def pad_and_pipes_exists
        if bmpsublist_id == 4 || bmpsublist_id == 5 || bmpsublist_id == 6 || bmpsublist_id == 7
          sublist_ids = Array.wrap([4, 5, 6, 7])
          pads_exists = false
          sublist_ids.each do |sublist_id|
            if Bmp.find_by_bmpsublist_id(sublist_ids) != nil
              pads_exists = true
            end #end if statement
          end #end each statment
        end #end first if statement
        return pads_exists
      end #end function
    

    我希望至少我的回答能激发某人想出一个更体面的方式。

答案 1 :(得分:0)

好吧,我愚弄了这一点,并得到了一些非常粗糙的工作。我定义了这样一个函数:

import sys, inspect, pytest

def mark_live_fixtures(module_name):
    testfunctions = [obj for name,obj
                     in inspect.getmembers(sys.modules[module_name])
                     if (inspect.isfunction(obj) and
                         name.startswith('test') and name != 'testall')]

    for func in testfunctions:
        if 'live_fixture' in inspect.getargspec(func).args:
            func = pytest.mark.live(func)

然后我可以在测试文件的底部粘贴mark_live_fixtures(__name__),并且似乎使用{{pytest.mark.live装饰将live_fixture装饰应用于该模块中的所有测试函数1}}。但这种方法至少存在两个问题:

  1. 我相信这只适用于在测试模块顶层定义的测试函数,我怀疑它是否适用于test class内的测试函数。
  2. 任何测试功能,例如@mock.patch或其他常见的测试修饰将具有可用于inspect.getargspec的正确参数内省(这是decorator模块存在的原因),因此它们不会被装饰为预期。
  3. 这当然有点难看,也许有人有更清洁的解决方案?