Deployment terms in Open Event Frontend

In Open Event Frontend, once a pull request is opened, we see some tests running on for the specific pull request like ‘Codacy’, ‘Codecov’, ‘Travis’, etc. New contributors eventually get confused what the tests are about. So this blog would be a walkthrough to these terms that we use and what they mean about the PR.

Travis: Everytime you make a pull request, you will see this test running and in some time giving the output whether the test passed or failed. Travis is the continuous integration test that we are using to test that the changes that the pull request you proposed does not break any other things. Sometimes you will see the following message which indicates that your changes is breaking something else which is not intended.

Thus, by looking at the Travis logs, you can see where the changes proposed in the pull request are breaking things. Thus, you can go ahead and correct the code and push again to run the Travis build until it passes.

Codacy: Codacy is being used to check the code style, duplication, complexity and coverage, etc. When you create a pull request or update the pull request, this test runs which checks whether the code followed certain style guide or if there is duplication in code, etc. For instance let’s say if your code has a html page in which a tag has an attribute which is left undefined. Then codacy will be throwing error failing the tests. Thus you need to see the logs and go correct the bug in code. The following message shows that the codacy test has passed.

Codecov:

Codecov is a code coverage test which indicates how much of the code change that is proposed in the pull request is actually executed. Consider out of the 100 lines of code that you wrote, only 80 lines is being actually executed and rest is not, then the code coverage decreases. The following indicates the codecov report.

Thus, it can be seen that which files are affected by what percent.

Surge:

The surge link is nothing but the deployment link of the changes in your pull request.

Thus, checking the link manually, we can test the behavior of the app in terms of UI/UX or the other features that the pull request adds.

References:

 

 

Writing Tests for ISO8601Date.java class of the Open Event Android App

ISO8601Date.java class of Open Event Android App was a util class written to perform the date manipulation functions and ensure the code base got more simpler and deterministic. However it was equally important to test the result from this util class so as to ensure the result returned by it was what we wanted. A test class named “DateTest.java” was written to ensure all the edge cases of conversion of the dates string from one timezone to another timezone were handled properly.

For writing unit tests, first we needed to add these libraries as dependencies in the app’s top level build.gradle file as shown below:

dependencies {
  testCompile 'junit:junit:4.12'
}

Then a JUnit 4 Test class, which was a Java class containing the required test methods was created. The structure of the class looked like this:

public class DateTest {
   @Test
   public void methodName() {
   }
}

Next step was including all the required methods which ensured the util class returned the correct results according to our needs. Various edge cases were taken into account by including functions like converting of date string from local time zone to specified timezone, from international timezone to local timezone, from local timezone to international timezone and many more. Some of the methods which were added in the class are shown below:

  • Test of conversion from local timezone to specified timezone:

This function aimed at ensuring the util class worked well with date conversion from local time zone to a specified timezone. An example as shown below was taken where the conversion of the date string was tested from UTC timezone to Singapore timezone.

@Test
public void shouldConvertLocalTimeZoneDateStringToSpecifiedTimeZoneDateString() {
    ISO8601Date.setTimeZone("UTC");
    ISO8601Date.setEventTimeZone("Asia/Singapore");

    String dateString1 = "2017-06-02T07:59:10Z";
    String actualString = ISO8601Date.getTimeZoneDateStringFromString(dateString1);
    String expectedString = "Thu, 01 Jun 2017, 23:59, UTC";
    Assert.assertEquals(expectedString, actualString);
}
  • Test of conversion from local timezone to international timezone:

This function aimed at ensuring the util class worked well with the date conversion from local timezone to international timezone. An example as shown below was taken where the conversion of the date string was tested from Amsterdam timezone to Singapore timezone.

@Test
public void shouldConvertLocalTimeZoneDateStringToInternationalTimeZoneDateString() {
    ISO8601Date.setTimeZone("Europe/Amsterdam");
    ISO8601Date.setEventTimeZone("Asia/Singapore");

    String dateString = "2017-06-02T02:29:10Z";
    String actualString = ISO8601Date.getTimeZoneDateStringFromString(dateString);
    String expectedString = "Thu, 01 Jun 2017, 20:29, GMT+02:00";
    Assert.assertEquals(expectedString, actualString);
}


Above were some functions added to ensure the conversion of a date string from one timezone to another was correct and thus ensured the util class was working properly and returned the results as required.

The last thing left was running the test to check the results the util class returned. For this we had to do two things:

  1. Sync the project with Gradle.
  2. Run the test by right clicking on the class and selecting “Run” option.

Through this we were able to run the test and check the output of the util class on different cases through the results which could be seen on the Android Monitor in the Android Studio.

Related Links:

  1. This link is about building effective unit tests in android. (https://developer.android.com/training/testing/unit-testing/index.html)
  2. This link is about the unit testing on date processing. (https://stackoverflow.com/questions/565289/unit-testing-code-that-does-date-processing-based-on-todays-date)

Unit testing JSON files in assets folder of Android App

So here is the scenario, your android app has a lot of json files in the assets folder that are used to load some data when in first runs.
You are writing some unit tests, and want to make sure the integrity of the data in the assets/*.json are preserved.

You’d assume, that reading JSON files should not involve using the Android Runtime in any way, and we should be able to read JSON files in local JVM as well. But you’re wrong. The JSONObject and JSONArray classes of Android are part of android.jar, and hence

 
JSONObject myJson = new JSONObject(someString);

The above code will not work when running unit tests on local JVM.

Fortunately, our codebase already using Google’s GSoN library to parse JSON, and that works on local JVM too (because GSoN is a core Java library, not specifically an Android library).

Now the second problem that comes is that when running unit tests on local JVM we do not have the getResources() or getAssets() functions.
So how do we retrieve a file from the assets folder ?

So what I found out (after a bit of trial and error and poking around with various dir paths), is that the tests are run from the app folder (app being the Android application module – it is named app by default by Android Studio, though you might have had named it differently)

So in the tests file you can define at the beginning

    public static final String  ASSET_BASE_PATH = "../app/src/main/assets/";

And also create the following helper function

    public String readJsonFile (String filename) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(ASSET_BASE_PATH + filename)));
        StringBuilder sb = new StringBuilder();
        String line = br.readLine();
        while (line != null) {
            sb.append(line);
            line = br.readLine();
        }

        return sb.toString();
    }

Now wherever you need this JSON data you can just do the following

        Gson gson = new GsonBuilder().create();
        events = gson.fromJson(readJsonFile("events.json"),
                Event.EventList.class);
        eventDatesList = gson.fromJson(readJsonFile("eventDates.json"), EventDates.EventDatesList.class);