[Android]Change locale with Android O

The method of changing locale changes in Android O.

+        if (Build.VERSION.SDK_INT >= 26) {
+            // getConfiguration moved from ActivityManagerNative to ActivityManagerProxy
+            activityManagerNativeClass = Class.forName(amn.getClass().getName());
+        }

Appium has already supported the change.
https://github.com/appium/io.appium.settings/blob/dc2cb22e1a2cb565fa49f0c56d00c604867554b5/app/src/main/java/io/appium/settings/handlers/LocaleSettingHandler.java#L57

Advertisements

[Android]Jetpack for test related environments

I’ve bet Truth since [Android]Checking Android Testing Support Library 1.0. I encountered an issue using AssertJ with ATSL 1.x and I talked about it in https://www.slideshare.net/KazuMatsu/20171215-andoirdtestnight before.

In a talk https://www.youtube.com/watch?v=wYMIadv9iF8 , Google starts to provide Jetpack. The pack has various libraries and test related libraries as well. For example, Espresso.

What I surprised is Truth Android extension. They announced the extension will be bundled in the pack. It means they will bundle Truth as an assertion library for Android. For me, the news was very good opportunity since it shows my prediction was a success.

Robolectric 4.0, Nitrogen and AndroidTestOrchestration were also interested.

We can see an announcement of Robolectric in http://robolectric.org/blog/2018/05/09/robolectric-4-0-alpha/ . According to the release note, we can implement test code like instrumented tests but can handle it via Robolectric. In the video, we can hear running test in no emulator environment and I predicted it was this feature. Recent years, Googlers have committed to Robolectric heard and I also thought it would integrate to one of the testing libraries.

@RunWith(AndroidJUnit4::class)
class OnDeviceTest {
  @get:Rule val rule = ActivityTestRule(NoteListActivity::class.java)

  @Test fun clickingOnTitle_shouldLaunchEditAction() {
    onView(withId(R.id.button)).perform(click())
    intended(hasAction(equalTo("android.intent.action.EDIT")))
  }
}

I’ve noted some interesting things for me in the Google IO especially test.

[Android]Use apkanalyzer to get apk data

It’s important to make configurations programmable to manage them codebase and enhance automation. Android has provided apkanalyzer to analyse test target apks easily. Before the command, we use aapt for example. But with the analyzer command, we can get apk related data from target release apks easily.

https://developer.android.com/studio/command-line/apkanalyzer

The below is a simple wrapper for adb and apkanalyzer written in Ruby. I’ve used it to integrate adb commands to integrate Ruby test code.
https://github.com/KazuCocoa/droid_adbs/

https://github.com/KazuCocoa/droid_adbs/blob/master/test/droid_adbs/analyzer_test.rb

[Android]New release of ATSL and new feature of composer

Lately, I’ve been using composer to run instrumented tests in the Android world. ([Android]composer and swarmer)

Today, I just found an interesting PR. => https://github.com/gojuno/composer/pull/138

The PR is emulating the behaviour like AndroidTestOrchestrator. As you know, the orchestrator has some limitations and it includes Parameterized tests aren't currently supported. It is JUnit4’s feature. So, the test support library has introduced JUnitParams.

The PR also has the same limitation. My project has been introduced the new Params so we don’t affect the limitations. But if you’d like to introduce the new composer’s feature, you should take care it.

I also just found interesting news.

Espresso 3.0.2, Runner 1.0.2, Rules 1.0.2, Monitor 1.0.2, AndroidTestOrchestrator 1.0.2 (2018-04-24) have been released!
https://developer.android.com/topic/libraries/testing-support-library/release-notes

They have some good improvements and fixes. For example:

  • Espresso 3.0.0 should NOT depend on test runner
  • ActivityTestRule doesn’t update Activity instance during configuration changes
  • Pass -e clearPackageData flag if you wish the orchestrator to run pm clear context.getPackageName() and pm clear targetContext.getPackageName() commands in between test invocations. Note, the context in the clear command is the App under test context.

etc.
Reading the release note, they fixed and improved many things for AndroidTestOrchestrator. That is brilliant.

Watching FB’s Android at Scale

I watched FB’s Android at Scale: https://code.facebook.com/posts/1958159731104103/android-scale-2018-recap/

I put my memo which I got interested in.

Automated Testing Practices @ Scale: Waseem Ahmad, Facebook

I know almost tips and same thought.

App Modularization and Module Lazy-Loading: Mona Huang, Instagram

  • How they separate their modulized app
  • How to separate their module to fit their structure

Screen Shot 2018-02-07 at 22.56.47

Model-View-Presenter @ Scale: Sam Thompson and Zach Westlake, Pinterest

  • Their Engineer increase and they have 40+ engineers in 2016
  • Their Approach

Screen Shot 2018-02-07 at 23.13.50

Screen Shot 2018-02-07 at 23.20.27

Screen Shot 2018-02-07 at 23.22.58

Conclusion

My company and team also start trying same thing and way to go.
Hopefully, some of our members talk our activities and tips publish to the world…

Read “Android アプリ設計パターン入門”

Androidアプリの設計パターンを読んだ。

自身の頭の整理、という感じですね。

個人的にはMVP/MVVMの話が一番よかったです。Activity/Fragmentやその他のもの。
Registoryレイヤはやっぱり色々なアーキテクチャでは安定していますが、PresenterやViewModelとかは今どうなのか、というところを把握するために、特に、

私自身、簡単な話だったり既存コードがMVP/MVVMとか、そこらへんの話はついていけるのですが、スクラッチで書けと言われるとちょっと参考を引っ張ってこないとサラでは書けないレベル。この書籍で、だいぶ頭の中の整理ができた気がします。

iOSもObjcから最近リリースされたし、mobile appのアーキテクチャは少し基盤ができた感じですかね。
https://www.objc.io/books/

[Android][Java][JUnit]Some links for JUnit 5

I discussed JUnit 5 with my team. I put some links and quotes in this post we discussed mainly then.

Core principle

Parameterized tests

https://github.com/junit-team/junit5/wiki/Core-Principles#parameterized-tests

Dynamic Test

http://www.baeldung.com/junit5-dynamic-tests

The DynamicTests are executed differently than the standard @Tests and do not support lifecycle callbacks. Meaning, the @BeforeEach and the @AfterEach methods will not be called for the DynamicTests.

https://stackoverflow.com/questions/44096293/how-are-dynamic-tests-different-from-parameterized-tests-in-junit-5#comment75557358_44114477

the dynamic test run was almost x10 faster to complete.

Migrating from JUnit 4 to JUnit 5

http://www.baeldung.com/junit-5-migration

BTW,

I tried to introduce some JUnit 5 thing in my private project to catch up with some syntax in JUnit 5.

https://github.com/KazuCocoa/EspressoEnv/commit/3c325488de59e5c644117048559a7d3b85a9abe3

[Android]Custom Lint for Android x Kotlin

We can implement some custom lint for Kotlin code.
So, I put an example the custom lint.

Some helpful links.

You can also find examples in the GitHub repositories. Let’s try to implement custom lint and reduce easy mistake from your projects.

Gradle

dependencies {
    compileOnly "com.android.tools.lint:lint-api:26.0.1"
    compileOnly "com.android.tools.lint:lint-checks:26.0.1"
}

sourceCompatibility = "1.8"
targetCompatibility = "1.8"

jar {
    manifest {
        attributes("Lint-Registry-v2": "your.custom.lint.package.LintClassName")
    }
}

Detector

class yourCustomLintDetector : Detector(), UastScanner {
    companion object {
        private val issueId = "yourCustomLint"
        private val issueDescription = "Description for yourCustomLint"
        private val issueExplanation = "Some more concrete explanation for yourCustomLint"
        // https://android.googlesource.com/platform/tools/base/+/master/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Category.java#122
        private val issueCategory = Category.CORRECTNESS
        private val issuePriority = 10
        private val issueSeverity = Severity.FATAL
        private val implementation = Implementation(yourCustomLintDetector::class.java, Scope.JAVA_FILE_SCOPE)

        internal val issue = Issue.create(issueId, issueDescription, issueExplanation, issueCategory, issuePriority, issueSeverity, implementation)
    }

    override fun applicableSuperClasses() = listOf("some.super.class.of.yourCustomLint")

    // If a target, class which inherits "some.super.class.of.yourCustomLint", has no "yourCustomLintName" method, then the following lines report it user.
    override fun visitClass(context: JavaContext, declaration: UClass) {
        val isOverridden = declaration.methods
                .firstOrNull { method -> method.isOverride && method.name.contains("yourCustomLintName") } != null

        if (!isOverridden) {
            declaration.uastAnchor?.let {
                context.report(issue, context.getLocation(it), "$issueDescription \n $issueExplanation")
            }
        }
    }
}

Registry

import your.custom.lint.package

class LintClassName : IssueRegistry() {
    override fun getIssues() = listOf(yourCustomLintDetector.issue)
}

check

Add the lines on your gradle dependencies.

dependencies {
  lintChecks project(':your-lint-project')
}

Test

You can implement tests for the custom rule.

https://android.googlesource.com/platform/tools/base/+/studio-master-dev/lint/libs/lint-tests/src/main/java/com/android/tools/lint/checks/infrastructure/LintDetectorTest.java

import com.android.tools.lint.checks.infrastructure.LintDetectorTest

class yourCustomLintDetectorNotOverrideTest : LintDetectorTest() {
    fun testBasic() {
        lint().files(
                LintDetectorTest.java("" +
                        "package test.pkg;\n" +
                        "import some.super.class.of.yourCustomLint;\n" +
                        "public class TestClass1 extends yourCustomLint {\n" +
                        "    @Override public void yourCustomLintName() {}\n" +
                        "}")) // an example
                .allowCompilationErrors()
                .run()
                .expect("Error message the lint should raise.....\n"
                        "1 errors, 0 warnings") // an example
    }

    override fun getDetector() = yourCustomLintDetector()

    override fun getIssues() = listOf(yourCustomLintDetector.issue)
}
import com.android.tools.lint.checks.infrastructure.LintDetectorTest

class yourCustomLintDetectorOverrideTest : LintDetectorTest() {
    fun testBasic() {
        lint().files(
                LintDetectorTest.java("" +
                        "package test.pkg;\n" +
                        "import some.super.class.of.yourCustomLint;\n" +
                        "public class TestClass1 extends yourCustomLint {\n" +
                        "    @Override public void yourCustomLintName() {}\n" +
                        "}")) // an example
                .allowCompilationErrors()
                .run()
                .expectClean()
    }

    override fun getDetector() = yourCustomLintDetector()

    override fun getIssues() = listOf(yourCustomLintDetector.issue)
}

Conclusion

I described an example to implement Custom Lint for Gradle plugin. I believe custom lint help your projects and if you work with some guys, the feature should help you more powerful.

Have a good testing 🙂

[Appium][Android]Scrolling to an element

Just for my memo

When we scroll views using Appium, then we have two ways to achieve it.

  1. Use UiScrollable

The below method is implemented in Ruby client.

  1. Use TouchAction or related actions.

The below is methods I used to implement as helper methods in my framework.

In my experience, 2 is almost stable than 1 since 1‘s behaviour depends on OS side and it also depends on devices,(and OSs).

[Android]Run orchestrator 1.0.0

Download apks from maven:

And install them and start the process like https://developer.android.com/training/testing/junit-runner.html

adb install -r path/to/orchestrator-1.0.0.apk
adb install -r path/to/test-services-1.0.0.apk

# Replace "com.example.test" with the name of the package containing your tests.
adb shell 'CLASSPATH=$(pm path android.support.test.services) app_process / \
  android.support.test.services.shellexecutor.ShellMain am instrument -w -e \
  targetInstrumentation com.example.test/android.support.test.runner.AndroidJUnitRunner \
  android.support.test.orchestrator/.AndroidTestOrchestrator'

If you have a custom runner, you can replace android.support.test.runner.AndroidJUnitRunner to yours.

After the above, you can start instrumentation tests via the orchestration layer.

./gradlew connectedAndroidTest