Android test build type
Testing : Build types, Product flavors and Continuous integration
- By default the build system defines two build types, debug and release . But in some cases that might not be enough for you, let’s «imagine» the situation when you or your team is developing but the backend is behind schedule. You could just hang around or do something else but now you’re so excited to continue working on this product that you create a small node.js project or a mock service so that you can continue your development.
- This could be the perfect situation to decide to add a build type. So let’s add a mock build type, so let’s say we want to switch between backend depending on the build type, there are serveral ways to do this.
Mock server example
- We can define BuildConfig fields, in this case we could define a field URI which we use to make a connection to our backend. This solution is the most straight forward, and is the cleanest code wise because the URI switches based on the build type.
- In order to get the URI in code: val URI = BuildConfig.URI
Default the build system adds a boolean field for debug , which is true only if the build type is debug. You could do this for other types as well. And use it to enable or disable http logging retrofit for example. You don’t want this to be enabled in a release version!
You can do this simply by checking if(BuildConfig.DEBUG)
Now why would you use this? I could just remove the lines when switching build, or I could just comment the logging real quick. You will forget and unexpected behavior will arise. But even more important, your code is does that for you now. And you can define tests for the different build types!
- So now we could add all the test folders like app/src/testDemoMock , within this folder you can write tests that will run from command-line/CI when the build type is MOCK.
- To test this we us ./gradlew test , if you encounter problems while your test run correctly in Android studio try using ./gradlew clean test
A product flavor is a «flavor» of a product.
The most used example is a free or paid app, an admin or user app. Let’s take another context: If Coffee is the product. You can have latte and mocha flavors. If we translate this back to development this means: Coffee is our «product» then latte and mocha are two coffee products with a different implementation. I’ll illustrate a bit more in depth and in code what that means.
Creating product flavors is pretty straight forward. We can do this by adding the following in the app/build.gradle
Since by default a release and debug build type is configured, we now have the following build variants
- debugDemo
- releaseDemo
- debugFull
- releaseFull
We can now define our flavor directories
- app/src/demo
- app/src/testDemo (app/src/androidTestDemo)
- app/src/full
- app/src/testFull (app/src/androidTestFull)
Using product flavors, let’s say we want a different string to show in our demo and full variant
We add the following to full/res/values/strings.xml and demo/res/values/strings.xml > Full version only.
Jenkins Android setup
- Ubuntu server (or desktop) running in VirtualBox
- Installed without any additional packages since setting up dns, apache etc is out of scope and depends on your enviroment
- Installing Java with apt-get is easy. First, update the package index: sudo apt-get update
- Check if Java is not already installed: java -version , «The program java can be found in the following packages» means it’s not installed
- To install JRE execute the following command: sudo apt-get install default-jre
- To install JDK use sudo apt-get install default-jdk
Installing android sdk
- wget http://dl.google.com/android/android-sdk_r24.4.1-linux.tgz
- tar -xvf android-sdk_r24.4.1-linux.tgz
- mv android-sdk-linux /usr/lib/android
- rm android-sdk_r24.4.1-linux.tgz
- cd /usr/lib/android/tools
- sudo apt-get install lib32stdc++6
- sudo apt-get install lib32z1
Get some coffee for the next part cause this takes a while.
There is a gradle plugin from Jake Wharton (https://github.com/JakeWharton/sdk-manager-plugin) that takes care of missing android dependencies. I don’t prefer this setup, cause gradle is not responsible for installing packages on the master server. I will prefer to do this with a cronjob that checks for new packages. * Jenkins now has a option that installs missing android packages if required (not tested yet)
Installing gradle Not required
This step is not required because you can set Jenkins to use the gradle/wrapper and specify which gradle version you want to use : distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip (Android studio automatically does this for you)
Because gradle is available trough PPA (Personal Package Archive), we’ll first have to add it to our system: sudo add-apt-repository ppa:cwchien/gradle
After we’ve added it, we’ll have to update our repository sudo apt-get update
sudo apt-get install grade —> If you don’t want the latest gradle version you can append a version gradle-1.5.0
IMPORTANT Check which version of gradle is running (!!) to check which Gradle version is required for which android gradle plugin. gradle -v , http://tools.android.com/tech-docs/new-build-system/version-compatibility
Gradle recommends NOT using gradle daemon in the CI environment!
- In case you got any of the following errors, you most likely have a mismatch gradle version issue.
- Could not find method jcenter() for arguments [] on repository container
- > Could not create plugin of type ‘AppPlugin’.
- wget —no-check-certificate -q -O — https://jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add —
- sudo sh -c ‘echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list’
- sudo apt-get update
- sudo apt-get install jenkins
After installing all components
- sudo apt-get update
- sudo apt-get upgrade
- sudo nano /etc/profile
- add at the end of file:
- Again there are «two approaches» here. One thing is to set everything correctly on your Ubuntu server, and than the Jenkins doesn’t need that much configuration anymore. I always make sure everything is set correctly on the Ubuntu server, that way Jenkins will always work also without the additional settings.
- To check/would if your build will succeed you can do this by changing to the Jenkins users sudo su jenkins
- Once you did this you should be able to use everything so lets do that
- git clone https://github.com/username/repo.git
- cd repoName
- gradle clean assemble —> if this succeeds the jenkins should be able to successfully build.
Configure Global Security
- I don’t work with any external user system so I let Jenkins maintain it’s own user database
- I use matrix-based security Anonymous needs read permission or you won’t be able to log in!
Plugins — Quality assurance
More information on how to setup quality assurance for android can be found in my repos.
Configuring Static Analysis Collecter Plug-in (Manage Jenkins -> Configure System)
* Failing build on corrupt setup file forces you to either do the setup correctly or skip it entirely. This way you can not be under the false assumption that everything is checked.
About
Android Testing with Build types, product flavors and Continous integration
Источник
TestBuildType
Build types define certain properties that Gradle uses when building and packaging your library, and are typically configured for different stages of your development lifecycle.
Test projects have a target application project that they depend on and build type matching works in the same way as library dependencies. Therefore to test multiple build types of an application you can declare corresponding build types here.
See configuring build types for more information.
Summary
Inherited functions
From class VariantDimension
Unit | addManifestPlaceholders( manifestPlaceholders : Map String , Any > ) Adds manifest placeholders. |
Unit | addManifestPlaceholders( manifestPlaceholders : Map String , Any > ) Adds manifest placeholders. |
Unit | buildConfigField( type : String , name : String , value : String ) Adds a new field to the generated BuildConfig class. The field is generated as: = ; This means each of these must have valid Java content. If the type is a String, then the value should include quotes. |
Unit | buildConfigField( type : String , name : String , value : String ) Adds a new field to the generated BuildConfig class. The field is generated as: = ; This means each of these must have valid Java content. If the type is a String, then the value should include quotes. Encapsulates per-variant CMake and ndk-build configurations for your external native build. Encapsulates per-variant CMake and ndk-build configurations for your external native build. Options for configuring Java compilation. Options for configuring Java compilation. Encapsulates per-variant configurations for the NDK, such as ABI filters. Encapsulates per-variant configurations for the NDK, such as ABI filters. |
Any | proguardFile( proguardFile : Any ) Adds a new ProGuard configuration file. There are two ProGuard rules files that ship with the Android plugin and are used by default: proguard-android-optimize.txt is identical to proguard-android.txt , except with optimizations enabled. You can use getDefaultProguardFileString to return the full path of the files. This method has a return value for legacy reasons. |
Any | proguardFile( proguardFile : Any ) Adds a new ProGuard configuration file. There are two ProGuard rules files that ship with the Android plugin and are used by default: proguard-android-optimize.txt is identical to proguard-android.txt , except with optimizations enabled. You can use getDefaultProguardFileString to return the full path of the files. This method has a return value for legacy reasons. |
Any | proguardFiles( vararg files : Any ) Adds new ProGuard configuration files. There are two ProGuard rules files that ship with the Android plugin and are used by default: proguard-android-optimize.txt is identical to proguard-android.txt , except with optimizations enabled. You can use getDefaultProguardFileString to return the full path of the files. This method has a return value for legacy reasons. |
Any | proguardFiles( vararg files : Any ) Adds new ProGuard configuration files. There are two ProGuard rules files that ship with the Android plugin and are used by default: proguard-android-optimize.txt is identical to proguard-android.txt , except with optimizations enabled. You can use getDefaultProguardFileString to return the full path of the files. This method has a return value for legacy reasons. |
Unit | resValue( type : String , name : String , value : String ) Adds a new generated resource. This is equivalent to specifying a resource in res/values. |
Unit | resValue( type : String , name : String , value : String ) Adds a new generated resource. This is equivalent to specifying a resource in res/values. |
Void ? | setManifestPlaceholders( manifestPlaceholders : Map String , Any > ) |
Void ? | setManifestPlaceholders( manifestPlaceholders : Map String , Any > ) |
Any | setProguardFiles( proguardFileIterable : Iterable * > ) Replaces the ProGuard configuration files. This method has a return value for legacy reasons. |
Any | setProguardFiles( proguardFileIterable : Iterable * > ) Replaces the ProGuard configuration files. This method has a return value for legacy reasons. Configure the shader compiler options. Configure the shader compiler options. |
Any | testProguardFile( proguardFile : Any ) Adds a proguard rule file to be used when processing test code. Test code needs to be processed to apply the same obfuscation as was done to main code. This method has a return value for legacy reasons. |
Any | testProguardFile( proguardFile : Any ) Adds a proguard rule file to be used when processing test code. Test code needs to be processed to apply the same obfuscation as was done to main code. This method has a return value for legacy reasons. |
Any | testProguardFiles( vararg proguardFiles : Any ) Adds proguard rule files to be used when processing test code. Test code needs to be processed to apply the same obfuscation as was done to main code. This method has a return value for legacy reasons. |
Any | testProguardFiles( vararg proguardFiles : Any ) Adds proguard rule files to be used when processing test code. Test code needs to be processed to apply the same obfuscation as was done to main code. This method has a return value for legacy reasons. Copies all properties from the given build type. It can be used like this: |
Unit | setMatchingFallbacks( vararg fallbacks : String ) |
Unit | setMatchingFallbacks( fallbacks : List String > ) PropertiesWhether to crunch PNGs. Whether this build type should generate a debuggable apk. Inherited propertiesEncapsulates per-variant CMake and ndk-build configurations for your external native build. Encapsulates per-variant CMake and ndk-build configurations for your external native build. Options for configuring Java compilation. Options for configuring Java compilation. The manifest placeholders. The manifest placeholders. Text file that specifies additional classes that will be compiled into the main dex file. Classes specified in the file are appended to the main dex classes computed using aapt . If set, the file should contain one class per line, in the following format: com/example/MyClass.class Text file that specifies additional classes that will be compiled into the main dex file. Classes specified in the file are appended to the main dex classes computed using aapt . If set, the file should contain one class per line, in the following format: com/example/MyClass.class Text file with additional ProGuard rules to be used to determine which classes are compiled into the main dex file. If set, rules from this file are used in combination with the default rules used by the build system. Text file with additional ProGuard rules to be used to determine which classes are compiled into the main dex file. If set, rules from this file are used in combination with the default rules used by the build system. Encapsulates per-variant configurations for the NDK, such as ABI filters. Encapsulates per-variant configurations for the NDK, such as ABI filters. Specifies the ProGuard configuration files that the plugin should use. There are two ProGuard rules files that ship with the Android plugin and are used by default: proguard-android-optimize.txt is identical to proguard-android.txt , except with optimizations enabled. You can use getDefaultProguardFileString to return the full path of the files. Specifies the ProGuard configuration files that the plugin should use. There are two ProGuard rules files that ship with the Android plugin and are used by default: proguard-android-optimize.txt is identical to proguard-android.txt , except with optimizations enabled. You can use getDefaultProguardFileString to return the full path of the files. Options for configuring the shader compiler. Options for configuring the shader compiler. The collection of proguard rule files to be used when processing test code. Test code needs to be processed to apply the same obfuscation as was done to main code. The collection of proguard rule files to be used when processing test code. Test code needs to be processed to apply the same obfuscation as was done to main code. Whether this build type is configured to generate an APK with debuggable native code. Specifies whether to enable code shrinking for this build type. By default, when you enable code shrinking by setting this property to true , the Android plugin uses ProGuard. Specifies whether the plugin should generate resources for pseudolocales. A pseudolocale is a locale that simulates characteristics of languages that cause UI, layout, and other translation-related problems when an app is localized. Pseudolocales can aid your development workflow because you can test and make adjustments to your UI before you finalize text for translation. When you set this property to true as shown below, the plugin generates resources for the following pseudo locales and makes them available in your connected device’s language preferences: en-XA and ar-XB . When you build your app, the plugin includes the pseudolocale resources in your APK. If you notice that your APK does not include those locale resources, make sure your build configuration isn’t limiting which locale resources are packaged with your APK, such as using the resourceConfigurations property to remove unused locale resources. Whether the build type is configured to generate an apk with debuggable RenderScript code. Specifies whether to enable shrinking resources for this build type. Whether test coverage is enabled for this build type. If enabled this uses Jacoco to capture coverage and creates a report in the build directory. The version of Jacoco can be configured with: Specifies a sorted list of build types that the plugin should try to use when a direct variant match with a local module dependency is not possible. Android plugin 3.0.0 and higher try to match each variant of your module with the same one from its dependencies. For example, when you build a «freeDebug» version of your app, the plugin tries to match it with «freeDebug» versions of the local library modules the app depends on. However, there may be situations in which your app includes build types that adependency does not. For example, consider if your app includes a «stage» build type, but a dependency includes only a «debug» and «release» build type. When the plugin tries to build the «stage» version of your app, it won’t know which version of the dependency to use, and you’ll see an error message similar to the following: In this situation, you can use matchingFallbacks to specify alternative matches for the app’s «stage» build type, as shown below: Note that there is no issue when a library dependency includes a build type that your app does not. That’s because the plugin simply never requests that build type from the dependency. Optimization level to use by the renderscript compiler. Returns whether multi-dex is enabled. This can be null if the flag is not set, in which case the default value is used. The associated signing config or null if none are set on the variant dimension. PropertiesisCrunchPngsWhether to crunch PNGs. Setting this property to true reduces of PNG resources that are not already optimally compressed. However, this process increases build times. PNG crunching is enabled by default in the release build type and disabled by default in the debug build type. isDebuggableWhether this build type should generate a debuggable apk. Content and code samples on this page are subject to the licenses described in the Content License. Java is a registered trademark of Oracle and/or its affiliates. Источник |