首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >python unitest -如何将"with“子句转换为setUp/tearDown

python unitest -如何将"with“子句转换为setUp/tearDown
EN

Stack Overflow用户
提问于 2019-08-12 14:47:15
回答 2查看 35关注 0票数 0

我有一个满是测试的类,这些测试以with子句开始,以设置一组复杂的环境和资源。每一行with都很长且重复。

我想把它们转换成setUp()teardDown()这样的单一实现

从本质上讲,我想要的东西如下:

代码语言:javascript
复制
    def setUp(self):
        self.unit = # some long initialisation

    def tearDown(self):
        self.unit.__exit__()

例如:假设这被简化为使用open()

代码语言:javascript
复制
class SomeTest(unittest.TestCase):
    def test_1(self):
        with open('filename', 'r') as f:
            # do testing with f
...
    def test_100(self):
        with open('filename', 'r') as f:
            # do testing with f

我会将其转换为:

代码语言:javascript
复制
  class SomeTest(unittest.TestCase):

    def setUp(self):
        self.f = open("filename', 'r')

    def tearDown(self):
        self.f.close()

    def test_1(self):
        # do testing with self.f
...
    def test_100(self):
        # do testing with self.f

现在这是可行的,因为文件有一个通用的、容易重现的__exit__对等物,即close()

在我们的例子中,__exit__处理程序相当复杂,依赖于类型,并且是有状态的-而且(除了测试目的)我们不想公开类似close()的应用程序接口(因为那样会增加有状态的复杂性),并且会允许客户端不按设计使用with子句。

有什么方法可以适当地调用__exit__吗?或者在每个测试用例周围集成with as子句?

EN

回答 2

Stack Overflow用户

发布于 2019-08-12 15:19:29

正如我所说的,我认为在tearDown方法中调用self.cm.__exit__(None, None, None)会很好地工作。

代码语言:javascript
复制
def tearDown(self):
    self.cm.__exit__(None, None, None)

然而,我开始考虑另一种你可以尝试的模式:

代码语言:javascript
复制
from contextlib import contextmanager
import unittest

class SomeTest(unittest.TestCase):
    @contextmanager
    def harness(self):
        with open('file.txt', 'r') as f1, open('file2.txt', 'w') as f2:
            try:
                yield f1, f2
            finally:
                pass

    def test_one(self):
        with self.harness() as (f1, f2):
            pass
票数 1
EN

Stack Overflow用户

发布于 2019-08-13 14:09:26

最后,装饰器可能比setUptearDown更优雅(跳过了很多参数)

代码语言:javascript
复制
def with_single_unit(fn):
    @functools.wraps(fn)
    def with_single_unit_(self):
        with SingleUnitStage(lotsa_args_skipped).select(lotsa_args_skipped) as unit:
            self.unit = unit
            fn(self)
    return with_single_unit_

class SomeTest(unittest.TestCase):

    @with_single_unit
    def test_a(self):
       # use self.unit

    @with_single_unit
    def test_b(self):
       # use self.unit

    @with_single_unit
    def test_c(self):
       # use self.unit
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57456732

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档