Python 接口模式和单元测试代码覆盖率
Python interface pattern and unit test code coverage
我在一个 python 项目中工作,使用 unittest
进行测试,coverage
进行代码覆盖。
我广泛使用接口模式,我注意到整体代码覆盖率受 "non tested interfaces".
的影响很大
考虑以下因素:
class IReader(object):
@abstractmethod
def read(self):
pass
class Reader(IReader):
def read(self):
# whatever
我测试了 Reader
但(显然)我没有测试 IReader
所以
pass
指令被标记为未包含在测试中。
有没有办法忽略来自 coverage
的接口?
由于这是我的第一个 python 项目,我这样做是否完全错误?
我真的不明白将这个 read
方法定义为单条指令有什么意义。如果你不需要它,让它提高 NotImplementedError
.
class IReader(object):
@abstractmethod
def read(self):
raise NotImplementedError
如 the docs 中指定的那样,抽象方法可以具有由 children 和 super()
使用的实现。但在你的情况下,它什么都不做。因此,除非你有充分的理由,否则你还不如让它升 NotImplementedError
.
(可以说,一个很好的理由可能是您的所有 children 出于某种原因调用 super().my_method()
的模式,因此您需要抽象 class 中所有方法的实现。 )
如何从覆盖率报告中排除抽象方法
无论如何,测试覆盖率只是您构建的一个指标:您要测试的代码中实际测试的部分。定义“您要测试的代码”由您决定。
您可以添加一个测试来检查抽象方法 returns NotImplementedError
或者只是 pass
es,如果您对此感兴趣的话。
或者您可能认为(这似乎是合理的)测试它是没有意义的,在这种情况下 excluding 覆盖率报告 #pragma: no cover
中的方法似乎是可行的方法:
class IReader(object): #pragma: no cover
@abstractmethod
def read(self):
pass
上面链接的文档页面显示了您还可以如何排除所有 NotImplementedError
方法,将其添加到您的配置文件中:
[report]
exclude_lines =
pragma: no cover
raise NotImplementedError
这样您就不必为每个抽象方法添加 pragma
。
2020 年编辑
我刚刚注意到@abstractmethod 装饰器。因为它阻止 class 被实例化,所以我不会引发 NotImplementedError
。参见 this other answer.
我只是将方法留空。从语法上讲,文档字符串就足够了
class IReader(object):
@abstractmethod
def read(self):
"""Read data"""
我在一个 python 项目中工作,使用 unittest
进行测试,coverage
进行代码覆盖。
我广泛使用接口模式,我注意到整体代码覆盖率受 "non tested interfaces".
的影响很大
考虑以下因素:
class IReader(object):
@abstractmethod
def read(self):
pass
class Reader(IReader):
def read(self):
# whatever
我测试了 Reader
但(显然)我没有测试 IReader
所以
pass
指令被标记为未包含在测试中。
有没有办法忽略来自 coverage
的接口?
由于这是我的第一个 python 项目,我这样做是否完全错误?
我真的不明白将这个 read
方法定义为单条指令有什么意义。如果你不需要它,让它提高 NotImplementedError
.
class IReader(object):
@abstractmethod
def read(self):
raise NotImplementedError
如 the docs 中指定的那样,抽象方法可以具有由 children 和 super()
使用的实现。但在你的情况下,它什么都不做。因此,除非你有充分的理由,否则你还不如让它升 NotImplementedError
.
(可以说,一个很好的理由可能是您的所有 children 出于某种原因调用 super().my_method()
的模式,因此您需要抽象 class 中所有方法的实现。 )
如何从覆盖率报告中排除抽象方法
无论如何,测试覆盖率只是您构建的一个指标:您要测试的代码中实际测试的部分。定义“您要测试的代码”由您决定。
您可以添加一个测试来检查抽象方法 returns NotImplementedError
或者只是 pass
es,如果您对此感兴趣的话。
或者您可能认为(这似乎是合理的)测试它是没有意义的,在这种情况下 excluding 覆盖率报告 #pragma: no cover
中的方法似乎是可行的方法:
class IReader(object): #pragma: no cover
@abstractmethod
def read(self):
pass
上面链接的文档页面显示了您还可以如何排除所有 NotImplementedError
方法,将其添加到您的配置文件中:
[report]
exclude_lines =
pragma: no cover
raise NotImplementedError
这样您就不必为每个抽象方法添加 pragma
。
2020 年编辑
我刚刚注意到@abstractmethod 装饰器。因为它阻止 class 被实例化,所以我不会引发 NotImplementedError
。参见 this other answer.
我只是将方法留空。从语法上讲,文档字符串就足够了
class IReader(object):
@abstractmethod
def read(self):
"""Read data"""