Search code examples
androidunit-testingjunitrobotiumandroid-testing

what to unit test, in android apps


My apps are mostly GUIs that communicate to a server for most of their information. If anything goes wrong it will usually be in the network call or making a wrong assumption about a JSON object.

Unit Tests are not good for these network-related and i/o related tasks, otherwise, they won't be called unit tests.

SO I am trying to gather the point of Unit Tests in my case. Why would I test if an Android button can click or an EditText can see what I type? I just don't understand the utility of implementing these tedious tests

private void initElements(){
    placeButton = (Button) findViewById(R.id.currplace);
    placeButton.setText(MainActivity.this.getString(R.string.findingLocation));
    placeButton.setEnabled(false);
    selectplaceLayout = (LinearLayout)findViewById(R.id.selectplaceLayout);
    selectplaceLayout.setVisibility(View.GONE);
    splash = (RelativeLayout)findViewById(R.id.splashbg);
    infoLayout = (LinearLayout)findViewById(R.id.infoLayout);
}

if this above method passed, which all my activities run in onCreate, then I know the app works. A unit test of this would be a redundant time-consuming thing to create. Time-consuming because I am not familiar with all the methods in the jUnit and Android testing framework.

So, long story short, what's the point? Is there a particular way I should be thinking about these tests? All examples and tutorials I've seen so far only talk about the simplest examples, for the sake of brevity, but I cannot think of any practical uses for unit tests in a predominately client-server app.

What am I expected to discover by accessing the android views that I already know I declared and initialized? I must be thinking about this in a too limited way

so, insight appreciated


Solution

  • There are lots of facets in your question, but to my opinion - you probably don't need unit-tests in your project.

    Unit tests really shine when you need lots of business logic to your project. In this case you probably want to divide your application into multiple layers (say, 3-tier architecture) to, among other, add some natural isolation for business-logic layer and cover it with safety net of unit tests.

    This safety net covers your ass during refactor of the business layer, and that's one of the main things you what from unit tests (TDD can offer some nice extra side effects though).

    However, it's not all unicorns and rainbows and unit-test may cost, and sometimes they cost a lot. Good unit tests are isolated (i.e. deal with small chunks of code). This means that you have to add layers of abstraction in order to put your classes under the test.

    This may have positive affect on your system or negative one. Layering makes your system more flexible with cost of increased complexity.

    Having that said - the value of the unit-tests is proportional to the amount of abstract business-logic you are going to introduce in your project. You may think of it also this way - if it is overkill to add abstract layers to your architecture - don't add unit-tests - they will only make things more complicated (architecture and build wise).

    Based on your description - your typical app tend to be pretty much presentation layer for some external server-side. It does not that much except presenting information on android handset and transforms user actions to commands to server-side where main business logic gets done (controlling).

    With this approach most of the code you probably write is related to "how to display this and that" or "how to signal server in this and that case". This sort of code is obviously heavily depend on platform and this mean that if you do want to put it under test you'll have to mock lots and lots of Android specific code\behavior.

    Now, Android is somewhat specific platform. It was designed to be both performance optimized and allow developers to start and produce apps quickly. Often this means some amount of "swiss-knife" classes you have use\extend and generally this speeds up writing code, but mocking those classes can become a real hell. Not to mention that you have to have understanding of how platform works under the hood to make those mock useful. In other words overhead from making those test is going to be high.

    Another thing that is wrong with testing presentation layers is that they tend to change much more dynamically than business layers. And, of course this mean that you'll have to refactor thee tests which adds even more overhead.

    I have to say one thing about various utility/helper classes though. Even if these classes are belong to presentation layer and do depend Android code, but do some rather non-trivial logic and it is easy to mock and write unit tests for them, it might actually be a good idea to do this. However, if you do have lots of such code - this is might be a signal that you haven't designed your architecture/layering well, and need to rethink what you are doing.

    In the end to answer your question you have to answer these questions first:

    Will it be overdesign to add abstract layer that is separated from the platform to your application (seems like in your case it will)? If yes - do not use unit-tests - they will only slow you down. If no - do use them.

    Are you going to refactor a lot? If that's large project with lots of code and thus maintenance - you probably will, so invest in layering and unit-tests (but, at a glance, it does not seem that this is your case). If that is not your case - do not bother with unit-tests and go fast.

    Do you need to mock platform a lot to write your unit tests? If yes (seems to be your case) - don't write unit tests - they do not worth the effort.

    Hope this will help.