tag:blogger.com,1999:blog-47960741715214961602024-03-13T07:11:38.018-07:00Las Cronicas de Lula"Comparte tu conocimiento. Es una forma de conseguir la inmortalidad" - Dalai LamaUnknownnoreply@blogger.comBlogger3125tag:blogger.com,1999:blog-4796074171521496160.post-89897044845234372582016-08-02T09:51:00.002-07:002016-08-02T09:56:26.541-07:00Git: mover una carpeta a otro repositorio manteniendo el histórico<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: right;">
<b><a href="http://lulachronicles.blogspot.nl/2016/06/git-how-to-move-folder-to-new-empty.html">English version here</a></b></div>
<div>
</div>
<br />
<div class="separator" style="-webkit-text-stroke-width: 0px; clear: both; color: black; font-family: Times; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; margin: 0px; orphans: auto; text-align: right; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px;">
<b><a href="http://lulachronicles.blogspot.nl/2016/06/git-how-to-move-folder-to-new-empty.html"><img alt="http://lulachronicles.blogspot.nl/2016/06/git-how-to-move-folder-to-new-empty.html" border="0" src="https://1.bp.blogspot.com/-fmXPcmb9Xjg/V5-iahVlOxI/AAAAAAAD6Pc/K-aECUH4aFE80VdzPFFAfePQ-QH28xUFgCLcB/s1600/english-flag.gif" style="cursor: move;" /></a></b></div>
<br />
<br />
Esto es cómo lo hice yo, no se si es la mejor forma pero funciona 100%<br />
<br />
<div>
Usé los comandos descriptos en este artículo <a href="https://help.github.com/articles/remove-sensitive-data/">https://help.github.com/articles/remove-sensitive-data/</a></div>
<div>
<br /></div>
<br />
<div>
</div>
<br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Times; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px;">
<ol style="text-align: left;">
<li>Dos repositorios: REPO_OLD con la carpeta que quiero mover, REPO_NEW un repositorio vacío a donde quiero mover la carpeta<br /> </li>
<li>Copiar todo (incluida la carpeta .git) desde el repositorio REPO_OLD al repositorio REPO_NEW (otra forma es clonar REPO_OLD en una nueva carpeta REPO_NEW)<br /> </li>
<li><b><u>IMPORTANTE:</u></b> borrar origin en el repositorio REPO_NEW: <b>git remote rm origin<br /> </b></li>
<li>Borrar en el repositorio REPO_NEW todas las carpetas que NO se quieren mover. Por ej. si la carpeta se llama FOLDER entonces<br /><br /><div class="p1">
<div style="margin: 0px;">
<span class="s1"><b>git filter-branch --force --index-filter ' git rm --cached --ignore-unmatch -r FOLDER/ ' --prune-empty --tag-name-filter cat -- --all</b><br /><br />hacerlo con todas las carpetas, una por una. Al final en REPO_NEW debería quedar solamente la carpeta que queremos mover. Si algunas carpetas todavía existen es porque tenían archivos que no se habían agregado a git, se pueden borrar a mano sin problemas.<br /> </span></div>
</div>
</li>
<li><div class="p1">
<div style="margin: 0px;">
<span class="s1">Ahora hay que setear el origin en REPO_NEW para que apunte al nuevo repositorio.<br /> </span></div>
</div>
<div class="p1">
<div style="margin: 0px;">
<span class="s1">Por ej. <b>git remote add origin git@bitbucket.org:someuser/REPO_NEW.git </b><br /> </span></div>
</div>
</li>
<li><div class="p1">
<div style="margin: 0px;">
<span class="s1">Pushear los cambios, forzando que sobreescriba en el origin: </span><b>git push origin --force --all<br /> </b></div>
</div>
</li>
<li>Ok, la carpeta está copiada, pero todavía existe en el otro repositorio. Se puede borrar usando el mismo comando del paso 4.<br /> </li>
<li><div class="p1">
<div style="margin: 0px;">
Listo</div>
</div>
</li>
</ol>
<div>
<div style="margin: 0px;">
<br /></div>
<div style="margin: 0px;">
<br /></div>
</div>
</div>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4796074171521496160.post-63515423653706242112016-08-02T00:29:00.003-07:002016-08-02T00:29:42.185-07:00Kotlin incluye codigo muerto en el bytecode<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<br class="Apple-interchange-newline" />
<div style="text-align: right;">
<b><a href="http://lulachronicles.blogspot.nl/2016/07/kotlin-includes-dead-code-in-generated.html">English version here</a></b></div>
<div style="text-align: right;">
<a href="http://lulachronicles.blogspot.nl/2016/07/kotlin-includes-dead-code-in-generated.html"><br /></a></div>
<div class="separator" style="clear: both; text-align: right;">
<b><a href="http://lulachronicles.blogspot.nl/2016/07/kotlin-includes-dead-code-in-generated.html"><img alt="http://lulachronicles.blogspot.nl/2016/07/kotlin-includes-dead-code-in-generated.html" border="0" src="https://1.bp.blogspot.com/-fmXPcmb9Xjg/V5-iahVlOxI/AAAAAAAD6Pc/K-aECUH4aFE80VdzPFFAfePQ-QH28xUFgCLcB/s1600/english-flag.gif" /></a></b></div>
<div>
<br /></div>
Hay dos presentaciones sobre Kotlin que disfrute mucho, ambas describen lo mejor de este nuevo lenguaje.<br />
<br />
<br />
<ul style="text-align: left;">
<li>Advancing Android development with Kotlin<br /><a href="https://realm.io/news/oredev-jake-wharton-kotlin-advancing-android-dev">https://realm.io/news/oredev-jake-wharton-kotlin-advancing-android-dev</a></li>
</ul>
<br />
<ul style="text-align: left;">
<li>Kotlin bytecode generation and runtime performance<br /><a href="http://www.slideshare.net/intelliyole/kotlin-bytecode-generation-and-runtime-performance">http://www.slideshare.net/intelliyole/kotlin-bytecode-generation-and-runtime-performance</a></li>
</ul>
<br />
<br />
<br />
Pero hay una cosa no descripta en esas presentaciones, un detalle sobre cómo Kotlin genera el bytecode:<br />
<br />
<div style="text-align: center;">
<i><b>Las 'inlined functions' de Kotlin no remueven el codigo muerto y lo incluyen en el bytecode.</b></i></div>
<br />
<br />
<br />
No es un gran problema ya que Proguard o una herramienta similar remueve el codigo muerto al optimizar las clases, pero en los proyectos Android a veces es necesario deshabilitar las optimizaciones de Proguard debido a la complejidad del proyecto, las librerias usadas, etc.<br />
<br />
<h3 style="text-align: left;">
Un ejemplo mostrando el código y el bytecode de Java y Kotlin</h3>
<br />
Veamos un ejemplo. Queremos mostrar mensajes de debug, pero no queremos incluir en el bytecode de la release build este código de debug.:<br />
<ul style="text-align: left;">
<li>En java podemos meter los logs dentro de una condición, chequeando una constante booleana. En este caso el compilador ignora todo lo que está dentro de la condición cuando el valor de la constante es falso.</li>
<li>En Kotlin podemos usar <i>inlined functions</i>, una gran ventaja de este lenguaje, para no chequear una cosntante cada vez que queremos mostrar un log. Un ejemplo de una <i>inlined function</i> en Kotlin<br /><br /><pre style="background-color: white; font-family: menlo; font-size: 9pt;"><span style="color: navy; font-weight: bold;">inline fun </span>debug(func: () -> String) {
<span style="color: navy; font-weight: bold;">if </span>(BuildConfig.<span style="color: #660e7a; font-style: italic;">DEBUG</span>) {
<span style="font-style: italic;">println</span>(func())
}
}</pre>
</li>
</ul>
<br />
<br />
Por ejemplo, mostramos un mensaje de debug dentro de un método llamado "doSomething"<br />
<br />
<table align="center" border="1" cellpadding="10" cellspacing="0" style="width: 585px;"><tbody>
<tr><th>Java</th></tr>
<tr><td><pre style="background-color: white; font-family: menlo; font-size: 9pt;"><span style="color: navy; font-weight: bold;">void </span>doSomething() {
<span style="color: navy; font-weight: bold;">if </span>(BuildConfig.<span style="color: #660e7a; font-style: italic; font-weight: bold;">DEBUG</span>) {
System.<span style="color: #660e7a; font-style: italic; font-weight: bold;">out</span>.println(<span style="color: green; font-weight: bold;">"Este es un mensaje de debug"</span>);
}
}</pre>
</td></tr>
</tbody></table>
<br />
<table align="center" border="1" cellpadding="10" cellspacing="0" style="width: 585px;"><tbody>
<tr><th>Kotlin</th></tr>
<tr><td><pre style="background-color: white; font-family: menlo; font-size: 9pt;"><span style="color: navy; font-weight: bold;">fun </span>doSomething() {
<span style="font-style: italic;">debug </span><span style="font-weight: bold;">{ </span><span style="color: green; font-weight: bold;">"Este es un mensaje de debug" </span><span style="font-weight: bold;">}</span></pre>
<pre style="background-color: white; font-family: menlo; font-size: 9pt;">}
</pre>
</td></tr>
</tbody></table>
</div>
<br />
+1 para Kotlin, menos código, limpio y simple.<br />
<br />
En Java podríamos crear un método static y poner la condición dentro del método, así tendríamos un código limpio como el de Kotlin, pero el compilador de Java no removería todos los llamados a la función y todos los strings de debug se incluirían en la build de release. Incluso optimizando con Proguard los llamados al método se remueven, pero no los parámetros, en realidad depende de la cantidad de pasos en la optimización dentro de proguard.properties.<br />
<br />
<br />
<h3 style="text-align: left;">
Veamos ahora el bytecode generado por Java y Kotlin.</h3>
<br />
Para analizar el bytecode uso el plugin de IntelliJ/Eclipse creado por los autores de la librería ASM, el <a href="http://asm.ow2.org/">OW2 Consortium</a>. Para Kotlin podría usar el plugin que viene con IntelliJ pero no tiene una opción para ignorar los números de linea, los labels y la info de stack.<br />
<br />
<br />
Bytecode generado cuando la constante <b>DEBUG</b> es <b>true</b><br />
<br />
<table align="center" border="1" cellpadding="10" cellspacing="0" style="width: 585px;"><tbody>
<tr><th>Java</th></tr>
<tr><td><pre style="background-color: white; font-family: menlo; font-size: 9pt;"> void doSomething() {
<b>getstatic</b> <span style="color: #38761d;">'BuildConfig.DEBUG'</span>,<span style="color: #38761d;">'Z'</span>
<b>ifeq</b> <span style="color: #741b47;">l0</span>
<b>getstatic</b> <span style="color: #38761d;">'java/lang/System.out'</span>,<span style="color: #38761d;">'Ljava/io/PrintStream;'</span>
<b>ldc</b> <span style="color: #38761d;">"Este es un mensaje de debug"</span>
<b>INVOKEVIRTUAL</b> java/io/PrintStream.println (Ljava/lang/String;)V
<span style="color: #741b47;">l0</span>
<b>return</b>
}
</pre>
</td></tr>
</tbody></table>
<br />
<table align="center" border="1" cellpadding="10" cellspacing="0" style="width: 585px;"><tbody>
<tr><th>Kotlin (el bytecode no es óptimo como el de java, ver el <u>subrayado</u>) </th></tr>
<tr><td><pre style="background-color: white; font-family: menlo; font-size: 9pt;"> public final static void doSomething() {
<b><u>nop</u></b>
<b>getstatic</b> <span style="color: #38761d;">'BuildConfig.DEBUG'</span>,<span style="color: #38761d;">'Z'</span>
<b>ifeq</b> <span style="color: #741b47;">l0</span>
<b>ldc</b> <span style="color: #38761d;">"Este es un mensaje de debug"</span>
<u><b>astore</b> 0</u>
<b><u>nop</u></b>
<b>getstatic</b> <span style="color: #38761d;">'java/lang/System.out'</span>,<span style="color: #38761d;">'Ljava/io/PrintStream;'</span>
<u><b>aload</b> 0</u>
<b>INVOKEVIRTUAL</b> java/io/PrintStream.println (Ljava/lang/Object;)V
<span style="color: #741b47;">l0</span>
<b>return</b>
}
</pre>
</td></tr>
</tbody></table>
<br />
+1 para Java, menos código que ejecutar.<br />
<br />
La diferencia no es grande pero Kotlin incluye algunos nops inútiles el la forma en que carga el string "Este es un mensaje de debug" es redundante, carga el string, lo guarda en el stack (astore 0), y lo carga de nuevo (aload 0).<br />
<br />
<br />
<br />
Bytecode generado cuando la constante <b>DEBUG</b> es <b>false</b><br />
<br />
<table align="center" border="1" cellpadding="10" cellspacing="0" style="width: 585px;"><tbody>
<tr><th>Java</th></tr>
<tr><td><pre style="background-color: white; font-family: menlo; font-size: 9pt;"> void doSomething() {
<b>return</b>
}
</pre>
</td></tr>
</tbody></table>
<br />
<table align="center" border="1" cellpadding="10" cellspacing="0" style="width: 585px;"><tbody>
<tr><th>Kotlin (dead code is <u>underlined</u>)</th></tr>
<tr><td><pre style="background-color: white; font-family: menlo; font-size: 9pt;"> public final static void doSomething() {
<b>nop</b>
<b>iconst_0</b>
<b>ifeq</b> <span style="color: #741b47;">l0</span>
<u> <b>ldc</b> <span style="color: #38761d;">"Este es un mensaje de debug"</span>
<b>astore</b> 0
<b>nop</b>
<b>getstatic</b> <span style="color: #38761d;">'java/lang/System.out'</span>,<span style="color: #38761d;">'Ljava/io/PrintStream;'</span>
<b>aload</b> 0
<b>INVOKEVIRTUAL</b> java/io/PrintStream.println (Ljava/lang/Object;)V</u>
<span style="color: #741b47;">l0</span>
<b>return</b>
}
</pre>
</td></tr>
</tbody></table>
<br />
+1 para Java, el compilador ignora el código dentro de la condición, pero el <i>inline</i> de Kotlin no hace ningún chequeo, simplemente copia y pega el código dentro del método, sin tener en cuenta el valor de la constante.<br />
<br />
<br />
<h3 style="text-align: left;">
Cómo evitarlo usando <i>gradle flavors</i></h3>
<br />
Lo que reomiendo para Kotlin es, en vez de chequear el valor de una constante, usar <i>gradle flavors</i>, el método para la build de debug muestra el mensaje sin chequear nada, el método de release no hace nada.<br />
<br />
<table align="center" border="1" cellpadding="10" cellspacing="0" style="width: 638px;"><tbody>
<tr><th>Debug flavor</th><th>Release flavor</th></tr>
<tr><td><pre style="background-color: white; font-family: menlo; font-size: 9pt;"><pre style="font-family: menlo; font-size: 9pt;"><span style="color: navy; font-weight: bold;">inline fun </span>debug(func: () -> String) {
<span style="font-style: italic;">println</span>(func())
}</pre>
</pre>
</td><td><pre style="background-color: white; font-family: menlo; font-size: 9pt;"><pre style="font-family: menlo; font-size: 9pt;"><span style="color: navy; font-weight: bold;">inline fun </span>debug(func: () -> String) {
}</pre>
</pre>
</td></tr>
</tbody></table>
<br />
<br />
Así el bytecode generado en la build de release es casi nulo .<br />
<br />
<br />
<table align="center" border="1" cellpadding="10" cellspacing="0" style="width: 585px;"><tbody>
<tr><th>Kotlin Bytecode: Debug flavor</th></tr>
<tr><td><pre style="font-family: menlo; font-size: 9pt;"> public final static void doSomething() {
<b>nop</b>
<b>ldc</b> <span style="color: #38761d;">"Este es un mensaje de debug"</span>
<b>astore</b> 0
<b>nop</b>
<b>getstatic</b> <span style="color: #38761d;">'java/lang/System.out'</span>,<span style="color: #38761d;">'Ljava/io/PrintStream;'</span>
<b>aload</b> 0
<b>INVOKEVIRTUAL</b> java/io/PrintStream.println (Ljava/lang/Object;)V
<b>return</b>
}
</pre>
</td></tr>
</tbody></table>
<br />
<table align="center" border="1" cellpadding="10" cellspacing="0" style="width: 585px;"><tbody>
<tr><th>Kotlin Bytecode: Release flavor</th></tr>
<tr><td><pre style="font-family: menlo; font-size: 9pt;"> public final static void doSomething() {
<b>nop</b>
<b>return</b>
}
</pre>
</td></tr>
</tbody></table>
<pre style="background-color: white; font-family: menlo; font-size: 9pt;"></pre>
<br />
<br />
Kotlin agrega un nop dentro del bytecode de release, pero es mejor que el código muerto incluido antes.<br />
<br />
<br />
Estamos resolviendo un gran problema con esto? Para la mayoria de los proyectos no, pero estos pequeños detalles pueden ser relevantes en proyectos que necesitan alta performance.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4796074171521496160.post-17400599873277446042016-08-01T12:18:00.002-07:002016-08-01T12:27:48.656-07:00Cómo ejecutar feature tests de Cucumber en android, pasos para Android Studio 2.1<div dir="ltr" style="text-align: left;" trbidi="on">
<br class="Apple-interchange-newline" />
<div style="text-align: right;">
<b><a href="http://lulachronicles.blogspot.nl/2016/07/how-to-run-cucumber-feature-tests-in.html">English version here</a></b></div>
<div style="text-align: right;">
<br /></div>
<div class="separator" style="clear: both; text-align: right;">
<b><a href="http://lulachronicles.blogspot.nl/2016/07/how-to-run-cucumber-feature-tests-in.html"><img border="0" src="https://1.bp.blogspot.com/-fmXPcmb9Xjg/V5-iahVlOxI/AAAAAAAD6Pc/K-aECUH4aFE80VdzPFFAfePQ-QH28xUFgCLcB/s1600/english-flag.gif" /></a></b></div>
<br />
<br />
<br />
Estos pasos no son para tests de UI, si quieres correr tests de integracion con Cucumber te recomiendo usar <a href="http://calaba.sh/">Calabash</a>.<br />
<br />
<br />
<ol style="text-align: left;">
<li>Crear un nuevo proyecto en Android Studio.<br /> </li>
<li>Abrir build.gradle y agregar las dependencias:<br /><br /><pre style="background-color: white; font-family: menlo; font-size: 9pt;">androidTestCompile <span style="color: green; font-weight: bold;">'junit:junit:4.12'</span>
androidTestCompile <span style="color: green; font-weight: bold;">group</span>: <span style="color: green; font-weight: bold;">'info.cukes'</span>, <span style="color: green; font-weight: bold;">name</span>: <span style="color: green; font-weight: bold;">'cucumber-java'</span>, <span style="color: green; font-weight: bold;">version</span>: <span style="color: green; font-weight: bold;">'1.2.2'</span>
androidTestCompile <span style="color: green; font-weight: bold;">group</span>: <span style="color: green; font-weight: bold;">'info.cukes'</span>, <span style="color: green; font-weight: bold;">name</span>: <span style="color: green; font-weight: bold;">'cucumber-core'</span>, <span style="color: green; font-weight: bold;">version</span>: <span style="color: green; font-weight: bold;">'1.2.2'</span>
androidTestCompile <span style="color: green; font-weight: bold;">group</span>: <span style="color: green; font-weight: bold;">'info.cukes'</span>, <span style="color: green; font-weight: bold;">name</span>: <span style="color: green; font-weight: bold;">'cucumber-html'</span>, <span style="color: green; font-weight: bold;">version</span>: <span style="color: green; font-weight: bold;">'0.2.3'</span>
androidTestCompile <span style="color: green; font-weight: bold;">group</span>: <span style="color: green; font-weight: bold;">'info.cukes'</span>, <span style="color: green; font-weight: bold;">name</span>: <span style="color: green; font-weight: bold;">'cucumber-jvm-deps'</span>, <span style="color: green; font-weight: bold;">version</span>: <span style="color: green; font-weight: bold;">'1.0.3'</span>
androidTestCompile <span style="color: green; font-weight: bold;">group</span>: <span style="color: green; font-weight: bold;">'info.cukes'</span>, <span style="color: green; font-weight: bold;">name</span>: <span style="color: green; font-weight: bold;">'gherkin'</span>, <span style="color: green; font-weight: bold;">version</span>: <span style="color: green; font-weight: bold;">'2.12.2'</span>
androidTestCompile <span style="color: green; font-weight: bold;">'info.cukes:cucumber-android:1.2.0@jar'</span>
androidTestCompile <span style="color: green; font-weight: bold;">group</span>: <span style="color: green; font-weight: bold;">'info.cukes'</span>, <span style="color: green; font-weight: bold;">name</span>: <span style="color: green; font-weight: bold;">'cucumber-junit'</span>, <span style="color: green; font-weight: bold;">version</span>: <span style="color: green; font-weight: bold;">'1.2.2'</span></pre>
<br />deben ser exactamente estos números de version. Las últimas versiones de Cucumber están compiladas con java 8, lo que no es soportado por android (por ahora)<br /><br /> </li>
<li>Necesitamos configurar en gradle que los tests sean ejecutados por Cucumber. Para eso hay que agregar en build.gradle el instrumentation runner, dentro de defaultConfig<br /><br /><pre style="background-color: white; font-family: menlo; font-size: 9pt;"><span style="color: #999999;">defaultConfig {
applicationId <span style="font-weight: bold;">"my.application.package"</span><span style="font-weight: bold;"> </span>minSdkVersion 14
targetSdkVersion 24
versionCode 1
versionName <span style="font-weight: bold;">"1.0"</span></span><span style="color: green; font-weight: bold;">
</span> testInstrumentationRunner <span style="color: green; font-weight: bold;">"cucumber.api.android.CucumberInstrumentation"
</span><span style="color: #999999;">}
</span></pre>
</li>
<li>Crea una nueva carpeta dentro de assets para los features de Cucumber en <b>src/androidTest/assets<br /> </b></li>
<li>Gradle no sabe nada de esta nueva carpeta con los features. Hay que configurar esta carpeta para que Cucumber pueda leer los features y ejecutarlos. Por ej. debajo de defaultConfig<br /><br /><pre style="background-color: white; font-family: menlo; font-size: 9pt;"><span style="color: #999999;">defaultConfig {
...
}
</span>sourceSets {
androidTest {
assets.srcDirs = [<span style="color: green; font-weight: bold;">'src/androidTest/assets'</span>]
}
}
</pre>
</li>
<li>Crear una nueva carpeta llamada "<b>features</b>" dentro de la carpeta de assets. Todos los archivos de features van a guardarse aquí (se puede usar subfolders). Acá un ejemplo de un feature que debe ir en un archivo en esta carpeta:<br /><br /><pre style="background-color: white; font-family: menlo; font-size: 9pt;">Feature: Calculator
Scenario Outline: a simple sum
Given I have numbers 2 and 3
When I sum
Then the result is 5
</pre>
</li>
<li><b>Este paso es muy importante. </b>Crea tus tests en el subpaquete "test" de tu paquete principal, por ejemplo <span style="color: #999999;">my.application.package</span>.test<br /><br />Ejemplo de un test para el feature anterior:<br /><br /><pre style="background-color: white; font-family: menlo; font-size: 9pt;"><span style="color: olive;">@CucumberOptions</span>(features = <span style="color: green; font-weight: bold;">"features"</span>)
<span style="color: navy; font-weight: bold;">public class </span>CalculatorFeatureTest {
<span style="color: navy; font-weight: bold;">private int </span><span style="color: #660e7a; font-weight: bold;">mNum1</span>;
<span style="color: navy; font-weight: bold;">private int </span><span style="color: #660e7a; font-weight: bold;">mNum2</span>;
<span style="color: navy; font-weight: bold;">private int </span><span style="color: #660e7a; font-weight: bold;">mResult</span>;
<span style="color: olive;">@Given</span>(<span style="color: green; font-weight: bold;">"^I have numbers (-*</span><span style="color: navy; font-weight: bold;">\\</span><span style="color: green; font-weight: bold;">d+) and (-*</span><span style="color: navy; font-weight: bold;">\\</span><span style="color: green; font-weight: bold;">d+)$"</span>)
<span style="color: navy; font-weight: bold;">public void </span>i_have_numbers_and(<span style="color: navy; font-weight: bold;">int </span>n1, <span style="color: navy; font-weight: bold;">int </span>n2) <span style="color: navy; font-weight: bold;">throws </span>Throwable {
<span style="color: #660e7a; font-weight: bold;">mNum1 </span>= n1;
<span style="color: #660e7a; font-weight: bold;">mNum2 </span>= n2;
}
<span style="color: olive;">@When</span>(<span style="color: green; font-weight: bold;">"^I sum$"</span>)
<span style="color: navy; font-weight: bold;">public void </span>i_sum() <span style="color: navy; font-weight: bold;">throws </span>Throwable {
<span style="color: #660e7a; font-weight: bold;">mResult </span>= <span style="color: #660e7a; font-weight: bold;">mNum1 </span>+ <span style="color: #660e7a; font-weight: bold;">mNum2</span>;
}
<span style="color: olive;">@Then</span>(<span style="color: green; font-weight: bold;">"^the result is (-*</span><span style="color: navy; font-weight: bold;">\\</span><span style="color: green; font-weight: bold;">d+)$"</span>)
<span style="color: navy; font-weight: bold;">public void </span>the_result_is(<span style="color: navy; font-weight: bold;">int </span>result) <span style="color: navy; font-weight: bold;">throws </span>Throwable {
<span style="font-style: italic;">assertEquals</span>(<span style="color: #660e7a; font-weight: bold;">mResult</span>, result);
}
}</pre>
<br />La annotation @CucumberOptions especifica la carpeta adentro de assets, en este caso "features"<br /> </li>
<li>En Android Studio, click derecho en el paquete con los tests, y elegir "Ejecutar tests en ..."<br /> </li>
<li>Listo</li>
</ol>
<div>
Estos pasos están basados en los pasos descriptos en <a href="http://mdzyuba.blogspot.nl/2015/01/cucumber-jvm-and-android-studio.html">http://mdzyuba.blogspot.nl/2015/01/cucumber-jvm-and-android-studio.html</a></div>
<br />
<br />
<br />
<br />
<br />
<br /></div>
Unknownnoreply@blogger.com0