我有一个Android应用程序项目,我想在其中添加自动化测试。为此,我想在Android Studio中使用Cucumber for java,并将这些测试直接执行到我的IDE中(使用Run / Debug配置)。
我在使用Android Studio 0.8.9的Windows 7 sp1 64位上。我添加了插件Gherkin
版本134.1007和Cucumber for Java
版本134.1007。我为Cucumber使用以下库:
这是我的项目结构:
TruckCalibrator/
.idea/
app/
build/
libs/
[libraries listed above in .jar format]
src/
main/
java/
com/
novomnetworks/
formeval/
truckcalibrator/
MainActivity.java
res/
AndroidManifest.xml
test/
assets/
features/
app_start.feature
java/
com/
novomnetworks/
formeval/
truckcalibrator/
test/
CucumberTest.java
build.gradle
build/
gradle/
这是我的gradle文件:
apply plugin: 'com.android.application'
android {
compileSdkVersion 20
buildToolsVersion '20.0.0'
defaultConfig {
applicationId "com.novomnetworks.formeval.truckcalibrator"
minSdkVersion 16
targetSdkVersion 20
versionCode 1
versionName "1.0"
testInstrumentationRunner "cucumber.api.android.CucumberInstrumentation"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
instrumentTest {
java.srcDirs = ['src/test/java']
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.github.satyan:sugar:1.3'
}
这是我的清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.novomnetworks.formeval.truckcalibrator"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.INTERNET" />
<instrumentation
android:name="cucumber.api.android.CucumberInstrumentation"
android:targetPackage="com.novomnetworks.formeval.truckcalibrator.test" />
<application
android:allowBackup="true"
android:icon="@drawable/launcher_icon"
tools:replace="icon"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:name="com.orm.SugarApp">
<uses-library android:name="android.test.runner" />
<meta-data android:name="DATABASE" android:value="form-eval.db" />
<meta-data android:name="VERSION" android:value="1" />
<meta-data android:name="QUERY_LOG" android:value="true" />
<meta-data android:name="DOMAIN_PACKAGE_NAME" android:value="com.novomnetworks.formeval.truckcalibrator.database" />
<activity
android:name=".MainActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
这是我的Cucumber步骤定义文件(CucumberTest.java
):
package com.novomnetworks.formeval.truckcalibrator.test;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
import cucumber.api.CucumberOptions;
import cucumber.api.PendingException;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import cucumber.api.junit.Cucumber;
import com.novomnetworks.formeval.truckcalibrator.MainActivity;
import com.novomnetworks.formeval.truckcalibrator.R;
import com.robotium.solo.Solo;
import org.junit.runner.RunWith;
/**
* Created by rroyer on 2014-10-24.
*/
@RunWith(Cucumber.class)
/*@CucumberOptions(monochrome = true,
tags = "@tags",
features = "src/test/assets/features/",
format = { "pretty","html: cucumber-html-reports", "json: cucumber-html-reports/cucumber.json" },
dryRun = false,
glue = "com.novomnetworks.formeval.truckcalibrator.test" )*/
public class CucumberTest extends ActivityInstrumentationTestCase2<MainActivity> {
private static final String TAG = "CucumberTest";
Solo solo;
public CucumberTest() {
super(MainActivity.class);
}
@Before
protected void before() throws Exception {
Log.d(TAG, "setUp");
super.setUp();
solo = new Solo(getInstrumentation(), getActivity());
getActivity().resetDB();
}
@After
protected void after() throws Exception {
Log.d(TAG, "tearDown");
solo.finishOpenedActivities();
super.tearDown();
}
@Given("^I started the app$")
public void i_started_the_app() throws Throwable {
solo.waitForActivity(MainActivity.class);
throw new PendingException();
}
@Then("I should see the action bar")
public void I_should_see_the_action_bar() throws Exception {
assertNotNull(getActivity().getMenu());
}
@Given("I am on the clients list")
public void I_am_on_the_clients_list() throws Exception {
solo.waitForFragmentById(R.layout.fragment_clients);
}
@Then("^I should see the clients list header$")
public void I_should_see_the_clients_list_header() throws Exception {
assertTrue(solo.searchText(solo.getString(R.string.clients)));
assertTrue(solo.searchText(solo.getString(R.string.sorted_by)));
assertNotNull(solo.getView(R.id.clients_spinner));
}
@Then("I should see the new client button")
public void I_should_see_the_new_client_button() throws Exception {
assertNotNull(solo.getView(R.id.action_new_client).isShown());
}
@Then("^I should see the clients list$")
public void I_should_see_the_clients_list() throws Exception {
assertNotNull(solo.getView(R.id.clients));
}
}
这是我的专题文件:
Feature: Démarrage de l'app
Scenario: La barre de menu devrait s'afficher
Given I started the app
Then I should see the action bar
Scenario: La liste des clients devrait s'afficher
Given I started the app
Then I should see the clients list header
And I should see the new client button
And I should see the clients list
当我运行我的Cucumber测试配置时,(截图)找到了功能,但我的步骤定义不是。输出说
Undefined step: Given I started the app
Undefined step: Then I should see the action bar
Undefined step: Given I started the app
Undefined step: Then I should see the clients list header
Undefined step: And I should see the new client button
Undefined step: And I should see the clients list
2 Scenarios (2 undefined)
6 Steps (6 undefined)
0m0,000s
You can implement missing steps with the snippets below:
@Given("^I started the app$")
public void i_started_the_app() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
[other similar suggestions...]
我在网上搜索了一整天而没有找到链接我的步骤定义文件的正确方法。我发现的每个帖子似乎都告诉人们在配置字段Glue
中提到测试包,这就是我所做的,但它没用。如果仔细查看我的CucumberTest.java文件,您可以看到我尝试使用@CucumberOptions
注释,但它没有更改结果。我也尝试过使用和不使用@RunWith(Cucumber.class)
注释。
我做错了什么?
答案 0 :(得分:0)
您正在抛出异常:throw new PendingException();
in
@Given("^I started the app$")
public void i_started_the_app() throws Throwable {
solo.waitForActivity(MainActivity.class);
throw new PendingException();
}
答案 1 :(得分:0)
我遇到了同样的问题,我想我已经解决了。首先,我们需要在所有黄瓜相关库上使用androidTestCompile
配置。请注意,我们需要使用@jar限定符来执行cucumber-android库,以避免gradle获取apklib文件而不是jar文件。例如:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
...
androidTestCompile 'info.cukes:cucumber-core:1.2.0'
androidTestCompile 'info.cukes:cucumber-java:1.2.0'
androidTestCompile 'info.cukes:gherkin:2.12.2'
androidTestCompile 'info.cukes:cucumber-html:0.2.3'
androidTestCompile 'info.cukes:cucumber-android:1.2.0@jar'
}
其次,我们不需要为Android Studio使用cucumber-java插件。我们需要在模拟器/设备上运行测试,而我无法找到使用cucumber-java插件设置的方法。相反,只需对运行配置使用Android Test,并将Specific Instrumentation Runner设置为cucumber.api.android.CucumberInstrumentation
。
我注意到的最后一件事是你不需要使用@RunWith
注释。只需在其中一个课程上使用@CucumberOptions
即可。
答案 2 :(得分:0)
您的测试应位于src/test
文件夹中,而不是ActivityInstrumentationTestCase2
此外,我将CucumberTest.java分离为Cucumber Runner的一个类,其中包含配置注释和从string strCmdText = string.Format("advfirewall firewall add rule name=\"BlockU\" protocol=any dir=in action=block remoteip={0}", ip);
ProcessStartInfo psi = new ProcessStartInfo("netsh.exe", strCmdText);
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
try
{
Process.Start(psi);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
扩展的包含胶水代码的单独类。
这里有一个使用Cucumber和Espresso而不是Robotium的Android Studio的运行示例: