2014-10-27 11 views
5

Ho un progetto di applicazione Android che voglio aggiungere test automatizzati al suo interno. Per questo mi piacerebbe usare Cucumber per Java in Android Studio ed eseguire questi test direttamente nel mio IDE (con una configurazione Run/Debug).Perché la definizione della mia cucumber non è definita in Android Studio

Sono su Windows 7 sp1 64 bit utilizzando Android Studio 0.8.9. Ho aggiunto i plugin Gherkin versione 134.1007 e Cucumber for Java versione 134.1007. Utilizzo le seguenti librerie di Cucumber:

  • cetriolo-android-1.1.8
  • cetriolo-core-1.1.8
  • cetriolo-html-0.2.3
  • cetriolo-java-1.1. 8
  • cetriolo-JUnit-1.1.8
  • cetriolo-JVM-deps-1.0.3
  • cetriolino-2.12.2
  • robotium-solo-5.2.1

Questa è la mia struttura del progetto:

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/ 

Questo è il mio file 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' 
} 

Questo è il mio manifesto:

<?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> 

Questo è il mio definizioni step Cucumber file (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)); 
    } 
} 

E questo è il mio file della caratteristica: si trovano

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 

Quando eseguo la mia configurazione di prova cetriolo, (screenshot sotto) Run/Debug configuration screenshot of my Cucumber test file Le caratteristiche ma le mie definizioni step non lo sono. L'output dice

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...] 

Ho cercato sul Web per un giorno intero senza trovare il modo corretto di collegare il mio file di definizioni di passo. Ogni post che trovo sembra dire alla gente di menzionare il pacchetto di test nel campo di configurazione Glue e questo è quello che ho fatto, ma è inutile. Se osservi attentamente il mio file CucumberTest.java, puoi vedere che ho provato con un'annotazione @CucumberOptions ma non ha modificato il risultato. Ho anche provato con e senza l'annotazione @RunWith(Cucumber.class).

Cosa sto sbagliando?

+0

primo sguardo, sembra che il pacchetto di destinazione nel manifesto di prova app è sbagliato - com.novomnetworks.formeval .truckcalibrator.test - remove .test – maszter

+0

Ho già provato con e senza, ho anche provato a mettere la mia classe CucumberTest non nel pacchetto di test (quindi è lo stesso pacchetto della mia classe MainActivity), ma ho avuto gli stessi errori –

risposta

0

si sta gettando un'eccezione: throw new PendingException();

in

@Given("^I started the app$") 
    public void i_started_the_app() throws Throwable { 
     solo.waitForActivity(MainActivity.class); 
     throw new PendingException(); 
    } 
+0

I non capisco cosa stai cercando di dirmi. Cucumber non è nemmeno in grado di trovare il metodo "i_started_the_app', quindi qual è l'accordo con il suo contenuto? Inoltre è esattamente ciò che il messaggio di errore mi dice di inserire nel mio metodo. –

+0

Devi rimuovere la nuova PendingException(); dal tuo codice. Quella linea lancia esattamente il messaggio che vedi nelle tue tracce. Ciò che il cetriolo sta dicendo è che puoi usare quel modello, ma devi rimuovere quella linea. Rimuovi quella linea e usa CucumberOptions piuttosto che @RunWith – mromer

+0

Ho rimosso la riga 'throw new PendingException();' e ho sostituito l'annotazione '@ RunWith' con l'annotazione' @ CucumberOptions', ma ottengo lo stesso identico errore. L'errore non dice da nessuna parte per rimuovere l'eccezione di lancio, dice di creare metodi con i comandi di eccezione di lancio ... –

0

mi sono imbattuto lo stesso problema e penso che ho risolto. Per prima cosa, dobbiamo usare le configurazioni androidTestCompile su tutte le librerie relative al cetriolo. Nota che dobbiamo usare il qualificatore @jar per la libreria cetriolo-android per evitare di gradle ottenere il file apklib invece del file jar.Per esempio:

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:[email protected]' 
} 

In secondo luogo, non hanno bisogno di utilizzare plug-cetriolo-java per Android Studio. Abbiamo bisogno di eseguire il test sull'emulatore/dispositivo, e non riesco a trovare un modo per configurarlo con il plugin cetriolo-java. Invece, è sufficiente utilizzare Android Test per le configurazioni di corsa e impostare il Runner per strumentazione specifica su cucumber.api.android.CucumberInstrumentation.

E l'ultima cosa che ho notato è che non è necessario utilizzare l'annotazione @RunWith. Basta usare @CucumberOptions su una delle tue classi e funziona.

0

i test dovrebbero essere nella cartella src/androidTest invece di src/test

Inoltre vorrei separare il CucumberTest.java in una sola classe per cetriolo Runner con le annotazioni di configurazione e una classe separata che si estende dalla ActivityInstrumentationTestCase2 contenente il codice colla.

Ecco un esempio di esecuzione per Android Studio utilizzando cetriolo e Espresso invece di Robotium:

https://github.com/neoranga55/CleanGUITestArchitecture

+0

Posso confermare che il test è in esecuzione su Android Studio, se lo eseguiamo utilizzando CucumberTestRunner.java, esiste un modo per eseguirlo uno scenario alla volta per un metodo di test più semplice? –

+0

Io uso i tag e quindi all'avvio del test filtro per tag per eseguire un solo caso di test, come: ./gradlew connectedAndroidTest -Ptags = "test-scenario-whatever-id-001" –