问题 在PyDev中初始化单元测试?


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

  1. 有办法有一个 setUpClass 在此类中的任何其他测试之前执行的方法?目前我只能得到 建立 工作,在课程的任何测试之前调用
  2. 有没有办法在执行任何测试之前调用全局初始化?就像是 setUpModule 我也无法使用PyDev单元测试运行。

在此先感谢任何答案和评论^^
切里奥沃尔坦

例:

class TestClass(unittest.TestCase):

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

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

如果我用它来运行 运行方式 - > Python单元测试 该 setUpClass 方法没有被调用。


6353
2018-03-25 09:36


起源

我在我的一些代码上尝试了这个 setUpClass() / tearDownClass() 当脚本使用'Python Run'运行时执行,但在使用'Python unit-test'时不执行。我认为这是PyDev的一个错误,我添加了一个 跟踪器神器 为了它。 - Steven T. Snyder
仅仅为了完整性,这是PyDev中的一个问题,并且已经针对2.0.1版本进行了修复(已经在当前的夜间版本中提供)。 - Fabio Zadrozny


答案:


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

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


7
2018-04-07 17:18



仅供记录:修复错误后,它也适用于我的机器! - Woltan
我有PyDev 2.1.0,我无法使setUpModule()工作。我是否正确,setUpModule()应该在测试用例之前的开头执行?代码在哪里?作为模块中的全局功能?它是否依赖于选定的语法(Python 2.6)? - sumid
@sumid setUpModule() 随着新的介绍 unittest Python 2.7中的模块。可以使用Python 2.6中的新单元测试功能 import unittest2,但我认为没有办法让PyDev认识到你想以这种方式运行你的测试。您可能希望将此问题与PyDev开发人员联系起来。看到 这个相关的线程 在PyDev用户论坛上。 - Steven T. Snyder


好吧,我会给这个镜头:我使用Pydev,并一直在探索使用“nosetests”来启动测试,所以它有点相关。我的解决方案完全是黑客攻击,但在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..."

不幸的是,这在使用nosetests时不起作用,但从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

额外

如果您正在使用nosetests进行进一步调查,那么您可以参考,请参阅“http://somethingaboutorange.com/mrl/projects/nose/1.0.0/writing_tests.html”。

你可以有:

包级别拆解:(这些存在于包级别的init脚本中)

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“运行单元测试......”。一个潜在的解决方案可能是编写一个使用nose运行测试的pydev插件......也许有人有一个?您可以将我的hack与调用常用模块函数的鼻子结合起来进行实际工作。理想的是我们的 在里面()会意识到以某种方式从Pydev发射。


5
2018-03-30 00:19



嗨,卡尔,这是一个有趣的黑客,并完全符合我的要求。太糟糕了,这种方法与nosetest框架不兼容。 - Woltan
嘿卡尔,再次感谢你的回答!如果我能找到时间,也许我会看一下PyDev的源代码,看看那里发生了什么。在那之前,我将使用你的'黑客'。 - Woltan


编辑:摘要

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

也许这将在PyDev的v2.0中修复,但与此同时,我认为我们必须这样做  使用 __init__() 相反,作为 卡尔斯 提示。

细节

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解释器,你可能会发现它是pre v2.7,如果我没记错的话,引入了setUpClass。

引用更新版本的python,我怀疑你的测试将按原样运行。


2
2018-04-04 13:46



嗨Mark,thx为你的答案,但我使用的是Python 2.7,它也被选为python解释器。所以这似乎不是问题。 cherio Woltan - Woltan
仅供参考我测试了PyDev的v2.0并且问题没有解决。 - Steven T. Snyder
感谢您查看Series8217。我认为这不值得一个错误报告,因为它感觉更像是一个功能请求。 - Mark Booth
我提交了一份 错误报告 因为它和开发人员立即解决了问题。如果你从更新PyDev 每晚更新网站 您将能够使用修复程序(版本2.0.1)下载最新版本。 - Steven T. Snyder


而不是使用 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)

unittest  文件 还有一些其他类似用途的例子,可以提供帮助。

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


0
2018-03-25 14:40



嗨mindcorrosive,thx为您的发布。这真是一个很好的方法,但我的问题是PyDev插件的PyUnit功能。以某种方式使用PyUnit主要是不被调用。因此,那里的任何初始化都不会被执行。也许PyUnit不是使用单元测试的最佳方式,但也许它确实支持一些初始化功能?! - Woltan