gradle使用junit_将Cucumberjvm与gradle和junit一起使用

gradle使用junit

Some time ago we were tasked with implementing an end to end UI automation testing framework to be used for an anonymous company’s native iOS and Android apps. We did a PoC of tools in the market and after some time we settled upon using Appium.

不久前,我们的任务是实施端到端UI自动化测试框架,以用于匿名公司的本机iOS和Android应用程序。 我们在市场上进行了工具的PoC,过了一段时间,我们决定使用Appium。

The constraints which were put upon us was that we needed to:

我们受到的限制是我们需要:

  • Use a language which was mobile developer-friendly

    使用对移动开发者友好的语言
  • Ensure that the framework could execute tests for both iOS and Android.

    确保该框架可以针对iOS和Android执行测试。
  • Use BDD to make this appealing to the Agile Delivery Managers (ADMs) for their story tracking, and manual QA’s who wanted to learn UI automation.

    使用BDD可以使Agile Delivery Manager(ADM)进行故事跟踪,以及希望学习UI自动化的手动QA吸引他们。

With the above in mind we settled upon using Cucumber JVM with the Appium Java client, and Gradle as the build management system. We chose Gradle because this is the default in the Android world hence we were appealing to one half of our mobile devs. Little did we know about the challenges which we would face as a result of that Gradle choice.

考虑到以上几点,我们决定将Cucumber JVM与Appium Java客户端一起使用,并使用Gradle作为构建管理系统。 我们选择Gradle是因为这是Android世界中的默认设置,因此我们吸引了一半的移动开发者。 对于Gradle的选择,我们将面临的挑战我们知之甚少。

When looking at the Cucumber JVM documentation we found a wealth of information about how we can use JUnit runners to execute our tests, however; it was focused on Maven.

当查看Cucumber JVM文档时,我们发现了大量有关如何使用JUnit运行器执行测试的信息。 它专注于Maven。

What about Gradle? The only official documentation which we found revolved around how we can use the Command Line Interface (CLI) via a Gradle task to execute the Cucumber JVM directly. (https://cucumber.io/docs/tools/java/#gradle) This is very limited in scope and didn’t scale for several things which we had our eye on.

那Gradle呢? 我们发现的唯一官方文档涉及如何通过Gradle任务使用命令行界面(CLI)直接执行Cucumber JVM。 ( https://cucumber.io/docs/tools/java/#gradle )这在范围上非常有限,并且无法扩展我们所关注的几件事。

Given that the majority of our team had predominantly come from a Maven background this was quite a challenge. It lasted a good few weeks and consisted of a lot of hair pulling, browsing Stack Overflow and drinking a lot of coffee or in my case tea (I don’t like the taste of coffee).

鉴于我们团队的大多数人主要来自Maven背景,这是一个很大的挑战。 它持续了好几个星期,包括拉很多头发,浏览Stack Overflow和喝很多咖啡,或者就我而言,喝茶(我不喜欢咖啡的味道)。

We started by first understanding how Gradle tasks work and the different types of tasks which you can have. We then combined this with the documentation which Cucumber has for Maven and JUnit and this is what we came up with. It may not be the most optimal solution, hence we welcome any feedback as to how this can be improved.

我们首先要了解Gradle任务的工作方式以及可以拥有的不同类型的任务。 然后,我们将其与Cucumber为Maven和JUnit提供的文档结合在一起,这就是我们想到的。 它可能不是最理想的解决方案,因此我们欢迎您就如何改善此问题提出任何反馈。

  1. We created a Cucumber Runner Class

    我们创建了一个Cucumber赛跑者班

We were using the fairly common src/main and src/test Java project layout so this class lived in its own package within src/test. It was aptly called MobileTestRunner and looked like this:

我们使用的是相当普通的src/mainsrc/test Java项目布局,因此此类位于src/test自己的包中。 它被恰当地称为MobileTestRunner ,看起来像这样:

package testRunners;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(
features = "src/test/resources/features/",
glue = "stepDefinitions",
strict = true,
plugin = {"pretty",
"html:target/cucumberReports/mobile/html",
"json:target/cucumberReports/mobile/json"
})
public class MobileTestRunner {
}

We were able to run this directly in the IDE and this would execute all features which existed in our src/test/resources/features folder and provide the relevant Cucumber reports. This was nice but what about executing only a small chunk of features, or executing this from the CLI? (the end goal was to have Continuous Integration (CI) executions after all)

我们能够直接在IDE中运行它,这将执行src/test/resources/features文件夹中存在的所有功能,并提供相关的Cucumber报告。 很好,但是仅执行一小部分功能或从CLI执行该功能呢? (最终目标是执行持续集成(CI))

2. We created a boilerplate Test task in our Gradle build script

2. 我们在Gradle构建脚本中创建了样板测试任务

Out of the box Gradle will look to run all Test Classes when this is invoked. If we therefore had multiple runners in the future we would have some weird and wonderful things going on. To overcome this we used the wonder that is Regex to target the single class in question, which is our MobileTestRunner

当被调用时,Gradle会立即运行所有测试类。 因此,如果将来有多个跑步者,我们将会发生一些奇怪而奇妙的事情。 为了克服这个问题,我们使用Regex来解决目标单一类,即MobileTestRunner

task regressionTests(type: Test) {include '**/MobileTestRunner*'}

3. We altered the behaviour of the Gradle test tasks in our build script to get the verbose information of our scenario executions

3. 我们在构建脚本中更改了Gradle测试任务的行为,以获取场景执行的详细信息

Those who use Cucumber know the value of the verbose output which you receive when executing scenarios in the feature files. Gradlesuppresses this information for test tasks out of the box, so a bit of Googling magic later we stumbled across this:

使用Cucumber的用户知道在功能文件中执行方案时收到的详细输出的值。 Gradles开箱即用地压制了这些信息以用于测试任务,因此稍后使用Googling魔术时,偶然发现了这一点:

tasks.withType(Test) {dependsOn cleanTest
testLogging {showStandardStreams = true}systemProperties System.properties}

We added the systemProperties line so that we could use Gradle’s systemProperty argument to override the runner’s default Cucumber options at the task execution level.

我们添加了systemProperties行,以便我们可以使用Gradle的systemProperty参数在任务执行级别覆盖跑步者的默认Cucumber选项。

4. We added values to change the Cucumber options in the task which was created in Step 2

4. 在步骤2中创建的任务中,我们添加了值来更改Cucumber选项。

Given the mobile test runner needs to be targeted for each task, we placed the regex in a variable at the top of our build script. This way we could alter it with a one line change in the future if we needed to.

鉴于需要为每个任务指定移动测试运行程序,我们将正则表达式放在构建脚本顶部的变量中。 这样,如果需要的话,我们将来可以只更改一行。

We also wanted the ability to target certain feature file sub folders as opposed to the whole directory when executing scenarios. We therefore created a variable to the parent directory which we could append to at the task level.

我们还希望能够在执行场景时将某些功能文件的子文件夹定位到整个目录,而不是整个目录。 因此,我们在父目录中创建了一个变量,可以将其附加到任务级别。

def testRunnerRegex = '**/MobileTestRunner*'
def mobileFeatureFilesPath = 'src/test/resources/features/'

With the above variables in place it was now just a case of altering the task which was created in Step 2, and adding in any more which we needed. We used Gradle’s systemProperty argument so that we could override the Cucumber options in the MobileTestRunner in order to execute what we wanted.

有了上述变量,现在只是更改在第2步中创建的任务,并添加我们需要的任何其他内容的情况。 我们使用Gradle的systemProperty参数,以便我们可以覆盖MobileTestRunner中的Cucumber选项,以便执行所需的操作。

For example:

例如:

task androidLoginTests(type: Test) {
include testRunnerRegex
systemProperty("cucumber.features", mobileFeatureFilesPath + "login")
systemProperty("cucumber.filter.tags", "@androidLogin")}

Would run our Android login tests which lived across the feature files in the login subdirectory (src/test/resources/features/login)

将运行我们的Android登录测试,该测试跨越了login子目录( src/test/resources/features/login )中的功能文件

Whereas this:

鉴于此:

task androidSmokeTests(type: Test) {include testRunnerRegex
systemProperty("cucumber.filter.tags", "@androidsmoke")}

Would run our Android smoke tests which lived across the feature files in all folders at the location src/test/resources/features

将运行我们的Android冒烟测试,该测试跨位置src/test/resources/features所有文件夹中的功能文件存在

5. We grouped the tasks and added in a description to make CLI executions a bit more readable

5. 我们将任务分组并添加了描述,以使CLI执行更具可读性

We found that when executing things through the CLI as is often the case when you’re testing out something to be added in CI, it was quite difficult to know what each task was doing, especially if it wasn’t correctly named. To that end we used Gradle’s very nice groups and description offering to make it a little easier on the eye when invoking gradle tasks

我们发现,当您通过CLI执行操作时(就像您在测试要添加到CI中的内容时的情况一样),要知道每个任务在做什么是非常困难的,特别是如果未正确命名。 为此,我们使用了Gradle很好的分组和描述功能,使在调用gradle tasksgradle tasks更加轻松

The group description was stored as a variable at the top of the file, to make it easier to update in the future if need be.

组描述作为变量存储在文件的顶部,以便将来在需要时更易于更新。

def appiumTesting="Appium UI Testing"task androidLoginTests(type: Test, group: appiumTesting) {description = "Execute login tests for Android"
include testRunnerRegex
systemProperty("cucumber.features", mobileFeatureFilesPath + "login")
systemProperty("cucumber.filter.tags", "@androidLogin")}

With all of the above in place we were now in a position to ensure that our Appium server was running with a connected device/emulator. From here we could then run whichever Gradle task we liked in order to run the cluster of tests which we needed to.

通过以上所有步骤,我们现在可以确保Appium服务器在连接的设备/仿真器上运行。 然后,我们可以从此处运行我们喜欢的任何Gradle任务,以运行所需的测试集群。

I hope that you have found this article useful, and that it saves you a lot of research, trial and error if you are in a similar situation :)

我希望您发现本文有用,并且如果您处于类似情况,它可以节省大量研究,反复试验的错误:)

My thanks to my peer Laxmikant Somni who was there with me pulling that hair and drinking that coffee to conquer this.

我要感谢我的同伴Laxmikant Somni ,他在那里陪着我拉着头发,喝着咖啡来解决了这个问题。

翻译自: https://medium.com/swlh/using-cucumber-jvm-with-gradle-and-junit-a0dc6e195c94

gradle使用junit

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值