gpt4 book ai didi

java - Spock 中 TestNG 数据提供者的模拟

转载 作者:行者123 更新时间:2023-11-28 21:19:58 25 4
gpt4 key购买 nike

我是 Spock 的新手,目前正在切换到它,但我继承了大量需要重新使用的测试配置文件。每个配置文件都是一个 JSON,与 Spec 类同名。对于每个测试方法,都有一个带有参数的映射列表,例如:

LoginSpec.json:
{
"My first test": [
{
"user": "user_one",
"role": "ADMIN"
},
{
"user": "user_two",
"role": "REPORTER",
"other_param": "other"
}
],

"Some Other Test Method": [
{
"url": "/lab1",
"button_name": "Show news popup"
}
]
}

TestNG 允许我在数据提供程序方法中传递测试方法名称,因此我可以根据测试类名称和测试方法名称返回映射列表。我的基类中只有一个数据提供者方法:

public Object[][] getData(String method) {
DataReader reader = new JsonReader()
return reader.parse(packageFullName, getClass().simpleName, method)
}

作为这种方法的结果,我得到了一个 map 数组,用于每个测试迭代。然后我将此方法指定为 DataProvider:

@Test(dataProvider = "getData", priority = 1)
void EULA_1(Map data) { <====
Pages.login.openLoginPage()
Pages.login.logIn(data.user) <====
...
}

这非常有效:在基类中声明 ones,它会自动接收测试并提供测试数据。

问题是有没有办法在 Spock 测试中应用类似的方法?

我想在我的基类中有一些 getData() 方法,我可以在其中根据测试方法名称读取测试参数,然后将它们传递到 where block 中。

我尝试使用我的 json 阅读器,如下所示:

def "My first test"() {
setup:
println(data)

when:
...
then:
...

where:
data = dataReader.parse("JobE2E", "LoginSpec.json", "My first test")
}

这个例子给了我所需的 map 列表,但有两个问题:

  1. data 这里是 map 的完整列表,而不是每次迭代一张 map ;
  2. 我被迫显式输入测试方法、类等的名称。

总结:实现接收测试方法名称并返回 map 列表的数据提供程序的最佳方法是什么?

最佳答案

您可以使用这种方法解决 data 的问题:

data << dataReader.parse('JobE2E', "${getClass().name}.json", 'My first test')

它将迭代 map 列表,因此每次测试迭代都将仅由该 map 参数化。


可以通过以下方式获取当前测试名称:

specificationContext.currentFeature.name

当前迭代名称为:

specificationContext.currentIteration.name

但是两者都不能在 where 部分访问,因为它在测试本身之前执行,其中只有来自共享上下文的值可用。 所以这里恐怕您必须手动输入测试名称。

更新:我在where部分为您找到了如何获取特征名称的解决方案。它是通过使用拦截器的自己的扩展实现的。

功能详细信息容器:

class FeatureDetails {
String name
}

扩展注解:

import org.spockframework.runtime.extension.ExtensionAnnotation

import java.lang.annotation.ElementType
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import java.lang.annotation.Target

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@ExtensionAnnotation(FeatureDetailsExtension.class)
@interface ShareFeatureDetails {
}

带有内联拦截器实现的 Spock 扩展:

import org.spockframework.runtime.extension.AbstractAnnotationDrivenExtension
import org.spockframework.runtime.model.FeatureInfo

class FeatureDetailsExtension extends AbstractAnnotationDrivenExtension<ShareFeatureDetails> {
def featureDetails = new FeatureDetails()

@Override
void visitFeatureAnnotation(ShareFeatureDetails annotation, FeatureInfo feature) {
feature.addInterceptor({ i ->
featureDetails.name = feature.name
feature.spec.allFields.each { f ->
if (f.type == FeatureDetails.class && f.readValue(i.getInstance()) == null) {
f.writeValue(i.getInstance(), featureDetails)
}
}
i.proceed()
})
}
}

扩展的用法示例:

class DataProviderSpec extends Specification {
@Shared
FeatureDetails currentFeature

@Unroll("Test #data.a * 2 = #data.b")
@ShareFeatureDetails
def 'test'() {
when:
println data

then:
data.a * 2 == data.b

where:
data << loadData()
}

@Unroll("Test #data.a * 3 = #data.b")
@ShareFeatureDetails
def 'another test'() {
when:
println data

then:
data.a * 3 == data.b

where:
data << loadData()
}

def loadData() {
// this is hard coded example
println "${getClass().name}.${currentFeature.name}"
if ('test' == currentFeature.name) return [[a: 1, b: 2], [a: 2, b: 4]]
if ('another test' == currentFeature.name) return [[a: 3, b: 9], [a: 4, b: 12]]
return []
// ... use load from data file (JSON, YAML, XML, ...) instead:
// return dataReader.parse("${getClass().name}.json", currentFeature.name)
}
}

上面例子的输出:

DataProviderSpec.test
[a:1, b:2]
[a:2, b:4]
DataProviderSpec.another test
[a:3, b:6]
[a:4, b:8]

第一个想法是在规范类中仅使用带注释的 String featureName 字段,但存在一个问题,即 visitFeatureAnnotation() 方法在每次调用期间与不同的规范实例一起工作loadData() 方法每次在第一个实例上执行。


注意:您还可以使用 @Unroll 注释添加具有特定于当前迭代的值的描述。例如:

@Unroll("Test #data.a * 2 = #data.b")
def 'test'() {
setup:
...
when:
...
then:
data.a * 2 == data.b

where:
data << getData('test')
}

def getData(String methodName) {
if ('test' == methodName) return [[a: 1, b: 2], [a: 2, b: 4]]
...
}

将产生:

Test 1 * 2 = 2
Test 2 * 2 = 4

关于java - Spock 中 TestNG 数据提供者的模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53173193/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com