Wednesday, July 27, 2016

How to run Cucumber feature tests in android, quick steps for Android Studio 2.1


These is not for UI tests, if you want to do acceptance tests emulating user interaction with the UI better use Calabash.


  1. Create a new android project in Android Studio.
     
  2. Open build.gradle and add the following dependencies
    androidTestCompile 'junit:junit:4.12'
    androidTestCompile group: 'info.cukes', name: 'cucumber-java', version: '1.2.2'
    androidTestCompile group: 'info.cukes', name: 'cucumber-core', version: '1.2.2'
    androidTestCompile group: 'info.cukes', name: 'cucumber-html', version: '0.2.3'
    androidTestCompile group: 'info.cukes', name: 'cucumber-jvm-deps', version: '1.0.3'
    androidTestCompile group: 'info.cukes', name: 'gherkin', version: '2.12.2'
    androidTestCompile 'info.cukes:cucumber-android:1.2.0@jar'
    androidTestCompile group: 'info.cukes', name: 'cucumber-junit', version: '1.2.2'

    it must be that exact version in all cucumber libraries, the latest version doesn't work due to they are compiled with java8, and java8 is not supported yet in android (soon, soon, we hope)

     
  3. We need to setup in gradle that the tests will be executed using Cucumber. Add the instrumentation runner in build.gradle, in the defaultConfig setup

    defaultConfig {
        applicationId "my.application.package"    minSdkVersion 14
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"    
        testInstrumentationRunner "cucumber.api.android.CucumberInstrumentation"
    }
     
  4. Create a new assets folder for the cucumber features in src/androidTest/assets
     
  5. This new folder is not recognized by gradle yet, set the new assets folder in build.gradle exactly, e.g. below the defaultConfig

    defaultConfig {
        ...
    }
    sourceSets {
        androidTest {
            assets.srcDirs = ['src/androidTest/assets']
        }
    }
     
  6. Create a new folder named "features" in the assets folder. All the feature files will stored be here (you can use subfolders). Example of a feature, can be on any file, cucumber doesn't care about the name of the file:

    Feature: Calculator
    
      Scenario Outline: a simple sum
        Given I have numbers 2 and 3
        When I sum
        Then the result is 5
     
  7. This is an important step. Create your tests in the subpackage "test" of your main package id, e.g. my.application.package.test

    A test example for the previous feature:

    @CucumberOptions(features = "features")
    public class CalculatorFeatureTest {
    
        private int mNum1;
        private int mNum2;
        private int mResult;
    
        @Given("^I have numbers (-*\\d+) and (-*\\d+)$")
        public void i_have_numbers_and(int n1, int n2) throws Throwable {
            mNum1 = n1;
            mNum2 = n2;
        }
    
        @When("^I sum$")
        public void i_sum() throws Throwable {
            mResult = mNum1 + mNum2;
        }
    
        @Then("^the result is (-*\\d+)$")
        public void the_result_is(int result) throws Throwable {
            assertEquals(mResult, result);
        }
    
    }

    The annotation @CucumberOptions specifies the folder inside the assets for all the feature files, in this case "features"
     
  8. Right click the package with the tests, and choose "Run tests in ..."
     
  9. You are done







Saturday, July 2, 2016

Be careful, Kotlin includes dead code in generated bytecode.


I enjoyed two Kotlin presentations. Both combined describe the best of this new language.






There is one thing not covered by those presentations, it is a tiny detail in how Kotlin generates the bytecode:

Kotlin inlined functions include dead code in the generated bytecode.



Not a big issue when using Proguard or similar tool to optimize/shrink the classes, but in in case of Android development sometimes is needed to avoid proguard optimization/shrink due to the complexity of the project, libraries, etc.

An example showing code and bytecode in Java and Kotlin


Let's see an example.  We want to log debug messages, but we dont want to include code for debugging purposes in the bytecode of the release build:
  • In java we call a log method inside a condition checking for a boolean constant, so the compiler ignores the code in the release build when the constant is false.
  • In Kotlin we use the advantage of inlined functions, we dont need to always include the condition when calling the log method. The function to log the message is the following

    inline fun debug(func: () -> String) {
        if (BuildConfig.DEBUG) {
            println(func())
        }
    }


We log the message inside a method named "doSomething"

Java
void doSomething() {
    if (BuildConfig.DEBUG) {
        System.out.println("This is a debug message");
    }
}

Kotlin
fun doSomething() {
    debug { "This is a debug message" }
}

+1 for Kotlin, cleaner code.

In java to have a cleaner code we could create a static utility method named "debug" and put the condition inside, but the compiler will include all the calls to "debug" in the bytecode of the release build. Even after optimizing with proguard the method calls will be removed, but not the parameters, depending on how many optimization passes we define in proguard.properties


Let's check now the bytecode generated by Java and Kotlin compilers.


To analyze the bytecode I use the plugin for IntelliJ/Eclipse made by the creators of the ASM library, the OW2 Consortium. I could use the Kotlin plugin included in IntelliJ in menu Tools -> Kotlin -> Show Kotlin Bytecode but it doesnt add an option to ignore the line numbers, unused labels and stack information.


Generated bytecode when DEBUG constant is true

Java
  void doSomething() {
    getstatic 'BuildConfig.DEBUG','Z'
    ifeq l0
    getstatic 'java/lang/System.out','Ljava/io/PrintStream;'
    ldc "This is a debug message"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   l0
    return
  }


Kotlin (useless bytecode is underlined)
  public final static void doSomething() {
    nop
    getstatic 'BuildConfig.DEBUG','Z'
    ifeq l0
    ldc "This is a debug message"
    astore 0
    nop
    getstatic 'java/lang/System.out','Ljava/io/PrintStream;'
    aload 0
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
   l0
    return
  }

+1 for Java.

Why? The difference is small but Kotlin includes some useless nops and the loading of the string "This is a debug message" is a bit dumb, loads the string, stores it, and loads it again.



Generated bytecode when DEBUG constant is false

Java
  void doSomething() {
    return
  }


Kotlin (dead code is underlined)
  public final static void doSomething() {
    nop
    iconst_0
    ifeq l0
    ldc "This is a debug message"
    astore 0
    nop
    getstatic 'java/lang/System.out','Ljava/io/PrintStream;'
    aload 0
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
   l0
    return
  }

+1 for Java, the java compiler ignores the code inside the condition, but Kotlin does a copy/paste of the code when inlining the function, not taking into account the value of the constant is always false.


A better approach using gradle flavors


What I recommend to do for Kotlin is, instead of checking for a constant, to use gradle flavors, the debug method in the flavor for the debug build shows the message, the debug method in the flavor for the release build does nothing.

Debug flavor Release flavor
inline fun debug(func: () -> String) {
    println(func())
}
inline fun debug(func: () -> String) {
}


Using it in this way we produce clean code and clean bytecode.


Kotlin Bytecode: Debug flavor
  public final static void doSomething() {
    nop
    ldc "This is a debug message"
    astore 0
    nop
    getstatic 'java/lang/System.out','Ljava/io/PrintStream;'
    aload 0
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
    return
  }

Kotlin Bytecode: Release flavor
  public final static void doSomething() {    
    nop
    return
  }



Kotlin adds a useless nop in the bytecode generated by the release flavor but is clean enough for our needs.


Are we solving a big issue here? Not really, but these small details help us to create clean code without adding an overhead in the compiled classes.









Tuesday, June 21, 2016

Git: How to move a folder to a new empty repository, with history included

I will not write an introduction of why we need to do this. This is how I did it, not sure if it is the best way but worked 100%:

I used the git commands described in this great article https://help.github.com/articles/remove-sensitive-data/

  1.  Two repos: REPO_OLD with the folder I want to move, REPO_NEW an empty repository where I will move the folder
     
  2. Copy everything (.git folder included) from REPO_OLD to REPO_NEW (another way is to clone REPO_OLD into a new folder REPO_NEW)
     
  3. DONT FORGET THIS: Remove the origin in REPO_NEW: git remote rm origin
     
  4. Delete in REPO_NEW all folders you DONT need. E.g. folder name is FOLDER then

    git filter-branch --force --index-filter ' git rm --cached --ignore-unmatch -r  FOLDER/ ' --prune-empty --tag-name-filter cat -- --all

    do it with all the folders one by one, at the end only the folder you need should be in REPO_NEW. If some folders still exist it is due to some files were not added to git, you can delete the folders manually, they are not in the git history anymore.
     
  5. Now set origin in REPO_NEW to the remote repository where you want to push this new repo.
     
    E.g. git remote add origin git@bitbucket.org:someuser/REPO_NEW.git 
     
  6. Push everything forcing overwrite history: git push origin --force --all
     
  7. Ok, it is copied, but not moved. Just delete the folder in REPO_OLD using the same command you used in step 4.
     
  8. Done



Sunday, May 15, 2016

Released a new android app: Radar Stats for LoL

Hi all,

I created a new app to analyze my games in League of Legends. I hope you enjoy it as I do.

The link to Google Play: https://play.google.com/store/apps/details?id=ar.ignaciotcrespo.lolradar

And the webpage: http://lolradarstats.com/

Some screenshots:







Later I will describe which libraries I am using in the app.

Any feedback is welcome.

Lula



Sunday, January 26, 2014

Just when you thought you knew a lot about development...

Just when you thought you knew a lot about development someone that knows more punch you directly in the face with a few wise words.

A friend recommended me "Clean Code" and "Clean Coder", by Robert Martin.

http://www.objectmentor.com/omTeam/martin_r.html

I feel like a child learning everything again. I love these books, it is the kind of technical thing that you need to read before going to sleep.







Wednesday, November 14, 2012

Android SDK Manager can't find latest updates!

I had a nice surprise today. After updating the ADT plugin in Eclipse it says that I must update the android tools.

Ok, one more time I opened the SDK Manager and searched for the updates. But wait... there is no updates. And Eclipse doesn't work! WTF?

"It must be a bad nightmare, take it easy" I think. Just do the obvious thing, close the SDK Manager and open it again. Stupid solution, it doesn't work.

Ok, something is bad, so I enter to the preferences and what I see is "Cache size" with the option "Delete cache". Oh yea! Now it works. God exists.

Stupid cache, you think you know everything, but I am better than you :D




Tuesday, November 6, 2012

Development tools I can't live without


Every developer has his own set of preferred tools. Me too. In my case all these tools are Java oriented because is the language I use more often. Obviously these are not the best tools you can find on internet, I'm sure you use other tools better and you hate my tools, but they gave me so many satisfactions that I think my work can't be finished without them. Too bad uh?

  • Eclipse: "naaaaaaaaaaa, no way" maybe you think. I understand people complaining this fantastic IDE, but I am in love with this tool. I tried all IntelliJ, Netbeans, etc. and I think I know Eclipse so well that I can face any problem that it can have, I accept it's buggy due to the free plugins we install all the time.
  • Findbugs: great free tool to detect common programming problems.
  • CheckStyle: the best tool to detect coding standard violations. I use it inside Eclipse of course.
  • UCDetector: Unused Code Detector. When your project it's really big you notice a lot of code that it is not being used. You can remove it automatically with proguard, but the best option is to delete it. Less code, less problems. This free Eclipse plugin will do the hard work for you, with many options, and allowing to remove multiple things with quickfix.
  • ASM Bytecode Plugin: amazing plugin to see the java bytecode in real time. Sometimes when you want to improve something it is good to check the bytecode, you will get some nice surprises. You can change the code, but the bytecode could be exactly the same or even worst.
  • Lint: checks for problems in Android projects. It is included in the android SDK and the ADT plugin.
  • Total Commander: wtf? This is not for java. Of course not, it is only THE file commander. Extremely powerful, and with lot of free plugins. It's for windows only but I use it with "wine" in MacOS. If you create a plugin the author will send you a personal license for free! Thanks Ghisler, you made me happy on christmas ;)
  • Sonar: easily receive reports with code coverage and errors.
  • PlantUML: combined with Javadoc is an amazing tool to add UML graphs to your documentation.
  • Google: do I need to put the link? When you don't know something he knows it :D
And the last thing I can say is: use the tools that are more comfortable for you, and use them well and wisely. You will love your daily job.

Cheers,

Lula