【问题标题】:Initialization of unit-test in PyDev?PyDev中单元测试的初始化?
【发布时间】:2011-07-22 18:56:54
【问题描述】:

我正在使用 PyDev 单元测试在 Eclipse 中对我的 python 代码进行单元测试。我右键单击相应的文件并选择Run As -> Python unit-test。关于这个插件,我有几个问题:

  1. 有没有办法让 setUpClass 方法在此类中的任何其他测试之前执行?目前我只能让 setUp 工作,这是在对课程进行任何测试之前调用的
  2. 有没有办法在执行任何测试之前调用全局初始化? setUpModule 之类的东西,我也无法使用 PyDev 单元测试运行。

提前感谢您的任何回答和评论^^
Cherio Woltan

示例:

class TestClass(unittest.TestCase):

  @classmethod
  def setUpClass(self):
      print "Setup"    

  def test1(self):
      print "Test1"
  def test2(self):
      print "Test2"

如果我使用 Run As -> Python unit-test 运行它,则不会调用 setUpClass 方法。

【问题讨论】:

  • 我在我的一些代码上尝试了这个,setUpClass() / tearDownClass() 在使用“Python Run”运行脚本时执行,但在使用“Python unit-test”时不执行。我认为这是 PyDev 的一个错误,我为此添加了 tracker artifact
  • 为了完整起见,这是 PyDev 中的一个问题,已在 2.0.1 版中得到修复(已在当前的夜间构建中可用)。

标签: python eclipse unit-testing eclipse-plugin pydev


【解决方案1】:

这是一个 PyDev 错误,已在 2.0.1 中修复。

由于 PyDev 2.0.0 及更早版本中的错误,setUpModule()tearDownModule()setUpClass()tearDownClass() 未在“Python 单元测试”运行配置中运行。在 2.0.1 中,它们在“Python 单元测试”和“Python 运行”配置中正确运行。我自己测试了验证。

【讨论】:

  • 仅作记录:修复错误后,它也可以在我的机器上运行!
  • 我正在使用 PyDev 2.1.0,但我无法让 setUpModule() 工作。我是否正确 setUpModule() 应该在测试用例之前开始执行?它应该在哪里?作为模块中的全局函数?它是否取决于所选语法(Python 2.6)?
  • @sumid setUpModule() 在 Python 2.7 中引入了新的 unittest 模块。可以通过使用import unittest2 在 Python 2.6 中使用新的单元测试功能,但我认为没有办法让 PyDev 认识到您希望以这种方式运行测试。您可能想向 PyDev 开发人员提出这个问题。请参阅 PyDev 用户论坛上的 this related thread
【解决方案2】:

好的,我试一试:我使用 Pydev,并且一直在探索使用“nosetests”来启动测试,所以它有点相关。我的解决方案完全是 hack,但在 PyDev 中说“Debug as UnitTest”时似乎确实有效:

print "before any tests (global) just once..."
class MyTestCase(unittest.TestCase):
   class_setup_called = False
   def __init__(self, test_name):
      unittest.TestCase.__init__(self, test_name)
      if not self.__class__.class_setup_called:
          self.setUpClass()
          self.__class__.class_setup_called = True
   @staticmethod
   def setUpClass():
      print "before first test only..."
   def setUp(self):
      print "before each test..."

不幸的是,这在使用鼻子测试时不起作用,但在从 pydev 运行时它确实起作用。我猜nosetests 被编码为在每个测试方法运行之前实例化测试对象,在这种情况下你的init方法就足够了。

关于鼻子测试,我不能说太多好话:

  • 支持异常和定时 测试。
  • 支持注释“属性”。
  • 与配置文件、覆盖范围和 xunit 结果报告集成。
  • 测试用例的递归发现和属性执行。

例子:

import unittest
@raises(TypeError)          
def test_forexceptions(self): 
    pass

@attr('benchmark')
@timed(5.0)
def test_benchmark(self):
    pass # do something real slow and run nosetests --with-profile -a benchmark

附加

如果您正在使用鼻子测试,那么如果您正在进一步调查,那么它已经涵盖了,请参阅“http://somethingaboutorange.com/mrl/projects/nose/1.0.0/writing_tests.html”。

你可以拥有:

包级拆解:(这些位于包级初始化脚本中)

def setup_package()
def teardown_package()

模块级拆解:

def setup_module()
def teardown_module()

班级等级:

class MyTestCase(unittest.TestCase):
    @classmethod
    def setup_class(cls): pass
    @classmethod
    def teardown_class(cls): pass

和测试方法级别:

class MyTestCase(unittest.TestCase):
    def setUp(self): pass
    def tearDown(cls): pass

我喜欢使用“setup_”名称,因为它很好地描绘了鼻子特定的入口点。通过命令行从nosetests 运行时,我已经很好地验证了这些工作。但它们不会从 Pydev “作为单元测试运行......”运行。一个潜在的解决方案可能是编写一个使用鼻子运行测试的pydev插件......也许有人有一个?您可以将我的技巧与调用通用模块函数的鼻子结合起来来完成实际工作。理想情况下,我们的 init() 会知道从 Pydev 以某种方式启动。

【讨论】:

  • 嗨,Carl,这是一个有趣的 hack,完全符合我的要求。太糟糕了,这种方法与鼻子测试框架不兼容。
  • 嗨,卡尔,再次感谢您的出色回答!如果我有时间,也许我会看一下 PyDev 的源代码,以了解其中发生了什么。在那之前,我会使用你的“hack”。
【解决方案3】:

编辑:摘要

使用调试器逐步检查您的测试用例,看起来这是 PyDev 的测试运行器不支持 setUpClass() 的限制,至少在我使用的 1.6.5 中不支持。

也许这将在 PyDev 的 v2.0 中得到修复,但与此同时,我认为我们将不得不 stick 改用 __init__(),正如 CarlS 所建议的那样。

详情

PyDev 1.6.5 PyDevTestSuite 类使用:

def run(self, result):
    for index, test in enumerate(self._tests):
        if result.shouldStop:
            break
        test(result)

        # Let the memory be released! 
        self._tests[index] = None

    return result

这与 python 2.6 中的 TestSuite.run() 非常相似,而 python 2.7.1 的 unittest 中的 TestSuite.run() 做得更多:

def run(self, result, debug=False):
    topLevel = False
    if getattr(result, '_testRunEntered', False) is False:
        result._testRunEntered = topLevel = True

    for test in self:
        if result.shouldStop:
            break

        if _isnotsuite(test):
            self._tearDownPreviousClass(test, result)
            self._handleModuleFixture(test, result)
            self._handleClassSetUp(test, result)
            result._previousTestClass = test.__class__

            if (getattr(test.__class__, '_classSetupFailed', False) or
                getattr(result, '_moduleSetUpFailed', False)):
                continue

        if not debug:
            test(result)
        else:
            test.debug()

    if topLevel:
        self._tearDownPreviousClass(None, result)
        self._handleModuleTearDown(result)
    return result

旧答案

我怀疑这可能与所引用的 Python 版本有关。

如果您检查 Window > Preferences > PyDev > Interpreter - Python 并查看正在使用哪个 Python Interpreter,您可能会发现它是 v2.7 之前的版本,如果我没记错的话,这里引入了 setUpClass。

参考较新版本的 python,我怀疑您的测试将按原样运行。

【讨论】:

  • 嗨,马克,谢谢你的回答,但我使用的是 Python 2.7,它也被选为 Python 解释器。所以这似乎不是问题。 cherio Woltan
  • 仅供参考,我测试了 PyDev v2.0,但问题没有解决。
  • 感谢您查看 Series8217。不过,我认为这不值得报告错误,因为它更像是一个功能请求。
  • 我为此提交了bug report,开发人员立即解决了问题。如果您从 nightly update site 更新 PyDev,您将能够下载带有修复程序的最新版本(版本 2.0.1)。
【解决方案4】:

不用使用unittest.main(),它会自动遍历所有测试类和单个测试,您可以分别从每个类加载测试并自行决定执行它们,包括在每个类测试之前进行必要的初始化。您也可以在所有这些之前进行一些全局初始化。请参阅下面的示例:

import unittest

class MyTestClass1(unittest.TestCase):

    def setUp(self):
         pass

    @classmethod
    def setUpClass(cls):
        pass

    def test1(self):
         pass

    # lots of tests

class MyTestClass2(unittest.TestCase):

    def setUp(self):
         pass

    @classmethod
    def setUpClass(cls):
        pass

    def test1(self):
         pass

    # another whole lot of tests


if __name__=="__main__":
    # add your global initialization code here
    global_initialization()

    # MyTestClass1 initialization:
    MyTestClass1.setUpClass() # python 2.7 only

    suite = unittest.TestLoader().loadTestsFromTestCase(MyTestClass1)
    unittest.TextTestRunner().run(suite)

    # MyTestClass1 initialization:
    MyTestClass2.setUpClass() # python 2.7 only

    suite = unittest.TestLoader().loadTestsFromTestCase(MyTestClass2)
    unittest.TextTestRunner().run(suite)

unittestdocumentation 有一些其他类似用法的示例可能会有所帮助。

编辑:直到现在我才知道,Python 2.7 似乎有一个setUpClass(),(应该是一个类方法,因此是装饰器)它似乎可以满足您的需要.但是,在 Python 2.6 中并非如此,您应该提供自己的初始化例程。

【讨论】:

  • 您好,mindterior,谢谢您的发帖。这确实是一个很好的方法,但我的问题是关于 PyDev 插件的 PyUnit 功能。以某种方式使用 PyUnit 不会调用 main 。所以那里的任何初始化都不会被执行。也许 PyUnit 不是使用单元测试的最佳方式,但也许它确实支持一些初始化功能?!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-13
  • 2011-03-09
相关资源
最近更新 更多