Slide 1

Slide 1 text

Continuous integration and deployment on Android DINO KOVAČ ANDROID TEAM LEAD @ INFINUM

Slide 2

Slide 2 text

ABOUT INFINUM • independent design and development agency • 90 employees • 15 Android Engineers • hundreds of projects

Slide 3

Slide 3 text

01 EARLY PROBLEMS

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

TITLE Nunc commodo mi dictum nisi iaculis ullamcorper donec bibendum.

Slide 7

Slide 7 text

02 CODE QUALITY

Slide 8

Slide 8 text

REGRESSIONS • the worst kind of bugs • some of them are easily detectable!

Slide 9

Slide 9 text

STATIC ANALYSIS TOOLS • lint • checkstyle • findbugs • pmd

Slide 10

Slide 10 text

ANDROID LINT • common android specific issues and best practices • LinearLayout orientation • using method introduced in SDK level > minSdk • missing super calls

Slide 11

Slide 11 text

CHECKSTYLE • helps to keep a consistent code style • highly configurable using config file • works well in combination with AS code style if(url.equals(otherUrl)){
 System.out.print("it's equal!");
 }
 
 if(url.equals(otherUrl))
 System.out.print("it's equal!");
 
 if (url.equals(otherUrl)) {
 System.out.print("it's equal!");
 }

Slide 12

Slide 12 text

PMD, FINDBUGS • warn you about common Java pitfalls • findbugs works on class files • pmd works on source files

Slide 13

Slide 13 text

JAVA.NET.URL

Slide 14

Slide 14 text

JAVA.NET.URL @Test
 public void urlEquals() throws Exception {
 URL url = new URL("https://infinum.co");
 URL otherUrl = new URL("https://www.infinum.co");
 
 Assert.assertEquals(url, otherUrl);
 }

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

JAVA.NET.URL - JAVADOCS • Two hosts are considered equivalent if both host names can be resolved into the same IP addresses; else if either host name can't be resolved, the host names must be equal without regard to case; or both host names equal to null. • Since hosts comparison requires name resolution, this operation is a blocking operation.

Slide 17

Slide 17 text

MATH.ABS • does not always return positive numbers! • integer values range from -2147483648 to 2147483647 Assert.assertTrue(Math.abs(Integer.MIN_VALUE) >= 0);

Slide 18

Slide 18 text

03 TESTING

Slide 19

Slide 19 text

TESTING APPROACHES • instrumentation tests - robotium / espresso • unit tests - plain JUnit • functional tests - robolectric

Slide 20

Slide 20 text

TESTS • we use a combination of unit tests and functional tests • centered around the clients needs and the specification

Slide 21

Slide 21 text

GREAT LIBRARIES • JUnit 4 • Mockito • OkHttp MockWebServer • Dagger 2 • assertj-android

Slide 22

Slide 22 text

@Test
 public void correctLoginRequest() throws Exception {
 String user = "testUserName";
 String pass = "testPass0&";
 
 enqueueResponse("sdk-login-response.json");
 Sdk.login(user, pass, mock(SdkCallback.class));
 
 RecordedRequest request = takeLastRequest();
 
 assertThat(request.getMethod()).isEqualTo("POST");
 assertThat(request.getPath()).isEqualTo("/login");
 assertThat(request.getHeader(“Accept")) .isEqualTo("application/json");
 assertThat(request.getHeader(“Content-Type")) .isEqualTo("application/x-www-form-urlencoded");
 assertThat(request.getBody().readUtf8()) .isEqualTo("login=" + user + "&password=" + "testPass0%26");
 }

Slide 23

Slide 23 text

@Test
 public void successfulLogoutDeletesTokens() throws Exception {
 stub(mockPlatform().preferenceStore().getAccessToken()) .toReturn("abcdefghijklmnopqrstuvwyxz0123456789");
 
 enqueueEmptyResponse(HttpURLConnection.HTTP_OK);
 Sdk.logout();
 
 verify(mockPlatform().preferenceStore()).clearAccessToken();
 verify(mockPlatform().preferenceStore()).clearRefreshToken();
 }

Slide 24

Slide 24 text

NO DETAILED SPECS? • when you have a detailed spec, tests like these are easy • when you don’t have it → the tests ARE the spec!

Slide 25

Slide 25 text

CONTINUOUS INTEGRATION • each push to the git repo triggers a build on the CI service • CI service checks out the code, runs static analysis and tests • if the build fails, you get notified • if you break the build you fix it!

Slide 26

Slide 26 text

CIRCLE CI • hosted CI service • nice android support • configurable via .yml file • support for saving and displaying build artifacts

Slide 27

Slide 27 text

CIRCLE CI - DOWNSIDES • integrates only with github • no support for x86 emulators • your code is ‘in the cloud’

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

BROKEN BUILDS • clients want their features done yesterday • project managers / product owners don’t care about broken builds • ‘we’ll fix the build after the release’

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

04 DEPLOYMENT

Slide 35

Slide 35 text

TITLE Nunc commodo mi dictum nisi iaculis ullamcorper donec bibendum.

Slide 36

Slide 36 text

AUTOMATIC DEPLOY FOR CLIENTS • for each push to the labs branch the release build is built • the CI build number is added to versionName: ‘1.0.0-b45’ • the .apk is uploaded to Infinum Labs • the last commit message is used as changelog

Slide 37

Slide 37 text

No content

Slide 38

Slide 38 text

Thank you! Questions please :) [email protected] @DINO_BLACKSMITH Visit infinum.co or find us on social networks: infinum.co infinumco infinumco infinum