我一直在做很多搜索,但我认为我并没有真正找到我一直在寻找的东西。我会尽力解释我正在尝试做的事情,希望有一个简单的解决方案,我会很高兴学到新的东西。
这最终是我想要完成的: 使用鼻子测试,使用属性选择器插件装饰一些测试用例,然后在命令行调用期间使用 -a 开关执行匹配标准的测试用例。然后将执行的测试的属性值存储在外部位置。我正在使用的命令行调用如下:
nosetests \testpath\ -a attribute='someValue'
我还创建了一个自定义的nosetest 插件,它存储测试用例的属性,并将它们写入外部位置。这个想法是我可以选择一批测试,并通过存储这些测试的属性,我可以稍后对这些结果进行过滤以用于报告目的。我通过使用类似于以下代码的“wantMethod”方法来访问我的插件中的方法属性:
def set_attribs(self, method, attribute):
if hasattr(method, attribute):
if not self.method_attributes.has_key(method.__name__):
self.method_attributes[method.__name__] = {}
self.method_attributes[method.__name__][attribute] = getattr(method, attribute)
def wantMethod(self, method):
self.set_attribs(method, "attribute1")
self.set_attribs(method, "attribute2")
pass
我几乎可以在所有测试中使用它,除了一种情况,其中测试使用“yield”关键字。发生的事情是生成的方法执行得很好,但是每个生成的函数的方法属性都是空的。
下面是我想要实现的示例。下面的测试检索一个值列表,并且对于这些值中的每一个,从另一个函数产生结果:
@attr(attribute1='someValue', attribute2='anotherValue')
def sample_test_generator(self):
for (key, value) in _input_dictionary.items()
f = partial(self._do_test, key, value)
f.attribute1='someValue'
yield (lambda x: f(), key)
def _do_test(self, input1, input2):
# Some code
根据我的阅读并认为我理解,当调用 yield 时,它会创建一个新的可调用函数,然后执行该函数。我一直在试图弄清楚如何从我的 sample_test_generator 方法中保留属性值,但我没有成功。我以为我可以创建一个部分方法,然后将属性添加到方法中,但没有运气。测试执行时完全没有错误,从我的插件的角度来看,方法属性似乎不存在,因此它们不会被记录。
我意识到这是一个非常复杂的问题,但我想确保我想要实现的目标的背景是明确的。我一直在努力寻找可以帮助我解决这个特殊情况的信息,但我觉得我现在遇到了一个绊脚石,所以我真的想请教专家一些建议。
谢谢。
** 更新 **
在阅读了反馈并进行了更多尝试之后,看起来如果我修改了 lambda 表达式,它将实现我想要的。事实上,我什至不需要创建偏函数:
def sample_test_generator(self):
for (key, value) in _input_dictionary.items()
yield (lambda: self._do_test)
这种方法的唯一缺点是测试名称不会改变。当我玩得更多时,它看起来像在鼻子测试中,当使用测试生成器时,它实际上会根据它包含的关键字更改结果中的测试名称。当我使用带有参数的 lambda 表达式时,也发生了同样的事情。
例如:
- 使用带有参数的 lamdba 表达式:yield (lambda x: self._do_test, "value1")
在nosetests插件中,当您访问测试用例名称时,它会显示为“sample_test_generator(value1)
- 使用不带参数的 lambda 表达式:yield (lambda: self._do_test)
在这种情况下,测试用例名称将是“sample_test_generator”。在我上面的例子中,如果字典中有多个值,那么 yield 调用会发生多次。但是,测试名称将始终保持为“sample_test_generator”。这并不像我获得唯一的测试名称但根本无法存储属性值那样糟糕。我会继续玩,但感谢到目前为止的反馈!
编辑
我忘了回来并提供关于我最终如何使它工作的最终更新,起初我有点困惑,在我仔细查看之后,我发现它有与如何识别测试有关:
我最初的实现假设每个被执行的测试都通过插件基类的“wantMethod”调用。当使用“yield”生成测试时,情况并非如此,因为此时测试方法已经通过了“wantMethod”调用。
但是,一旦通过“yeild”调用生成测试用例,它确实会通过插件基类的“startTest”调用,这就是我最终能够成功存储属性的地方。
所以简而言之,我的测试执行顺序如下所示:
鼻子 -> wantMethod(method_name) -> yield -> startTest(yielded_test_name)
在我对 startTest 方法的覆盖中,我有以下内容:
def startTest(self, test):
# If a test is spawned by using the 'yield' keyword, the test names would be the parent test name, appended by the '(' character
# example: If the parent test is "smoke_test", the generated test from yield would be "smoke_test('input')
parent_test_name = test_name.split('(')[0]
if self.method_attributes.has_key(test_name):
self._test_attrib = self.method_attributes[test_name]
elif self.method_attributes.has_key(parent_test_name):
self._test_attrib = self.method_attributes[parent_test_name]
else:
self._test_attrib = None
有了这个实现,连同我对 wantMethod 的覆盖,父测试用例产生的每个测试也继承了父方法的属性,这正是我所需要的。
再次感谢所有发送回复的人。这是一次很好的学习经历。