android unit testing

Posted by keith73 on Mon, 20 May 2019 22:02:48 +0200

In fact, every time you create a new andorid project, you will automatically import JUnit. What is this? Many times I feel that this thing is useless, and I delete it inadvertently, until I see Clean Code, I realize that this thing seems very important, so I start to learn by myself. The following basic steps are recorded:

1 (model) build.gradle join

(usually automatically generated)

dependencies{
 androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    testCompile 'junit:junit:4.12'

     compile 'com.android.support.test.espresso:espresso-core:2.2.2'
    compile 'com.android.support.test:runner:0.5'
    compile 'com.android.support.test:rules:0.5'
}

If you don't know the version number, you can use File - > Project Structure - > click on the module that needs unit testing - > click on Dependencies - > + number - > Library Dependency - > search the beginning part such as com.android.support.test on the right panel, and the corresponding click will automatically import.

2. Add in manifest

It's all in the application tag (I'm wrong to add it outside):

  <uses-library android:name="android.test.runner" />

        <instrumentation
            android:name="android.test.InstrumentationTestRunner"
            android:label="@string/app_name"
            android:targetPackage="." />

3. General test:
Right-click on the class name - > Go To - > Test - > Create New Test, and select the method to test and setUp/@Before
Here I refer to the blog in the brief book. Click jump

(Add:)

public class Calculator {
    public double sum(double a, double b){
        return a+b;
    }

    public int getAllBetweenNumsSum(int start,int end){
        return (start+end)*(end-start+1)/2;
    }



    public double substract(double a, double b){
        return 0;
    }

    public double divide(double a, double b){
        return 0;
    }

    public double multiply(double a, double b){
        return 0;
    }
}

In CaculatorTest:

public class CalculatorTest {
    private Calculator mCalculator;

    @Before
    public void setUp() throws Exception {
        mCalculator = new Calculator();
    }

    @Test
    public void testSum() throws Exception {
        testSum(2,3);
        testSum(5,10);
        testSum(-100,7);
    }

    private void testSum(int start,int end) {
        int sum1 = mCalculator.getAllBetweenNumsSum(start,end);
        int sum2 = getAllBetweenNumsSum2(start,end);
        assertEquals(sum1,sum2);
    }

    public int getAllBetweenNumsSum2(int start,int end){
        int sum = 0;
        for(int i = start; i <= end; i++){
            sum += i;
        }
        return sum;
    }

    @Test
    public void testSubstract() throws Exception {
        assertEquals(1d, mCalculator.substract(5d, 4d), 0);
    }

    @Test
    public void testDivide() throws Exception {
        assertEquals(4d, mCalculator.divide(20d, 5d), 0);
    }

    @Test
    public void testMultiply() throws Exception {
        assertEquals(10d, mCalculator.multiply(2d, 5d), 0);
    }


}

As you can see, there is a small arrow in front of each part to run the test. When it passes, the test bar below is green, otherwise it is red. The color of the test bar can judge whether it passes the test. Asset Equals is used to test. When the content is unequal, the test fails. The Caculate example here has been slightly modified. I tested whether the formula (first + last) * number of items / 2 was correct.

android testing

In fact, you should note that there are two test packages, test and Android test. Test is a computational test for parts without ui. Android test can test ui, and it also follows the test of simplified books. Click jump:

Write a test Activity:

public class TestUnitActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_unit);
    }

    public void sayHelloToEditInputContent(View v){
        TextView txtShowBtnResult = (TextView) findViewById(R.id.txt_show_click_result);
        EditText edtInputBtnContent = (EditText) findViewById(R.id.edt_input_click_content);
        txtShowBtnResult.setText("Hello, " + edtInputBtnContent.getText().toString() + "!");
    }
}

The corresponding xml layout file: (Forgive me for obsessive-compulsive disorder, be sure to change the EditView and TextView and the name of the click event)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="5dp"
    android:paddingLeft="5dp"
    android:paddingRight="5dp"
    android:paddingTop="5dp"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/txt_show_click_result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hello world!" />

    <EditText
        android:id="@+id/edt_input_click_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView"
        android:hint="Enter your name here" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/edt_input_click_content"
        android:onClick="sayHelloToEditInputContent"
        android:text="Say hello!" />
</RelativeLayout>

Create a new class in the Android Test section:

public class MainActivityInstrumentationTest {
    private static final String STRING_TO_BE_TYPED = "Peter";

    @Rule
    public ActivityTestRule<TestUnitActivity> mActivityRule = new ActivityTestRule<>(
            TestUnitActivity.class);

    @Test
    public void sayHello(){
        onView(withId(R.id.edt_input_click_content)).perform(typeText(STRING_TO_BE_TYPED), closeSoftKeyboard()); //line 1

        onView(withText("Say hello!")).perform(click()); //line 2

        String expectedText = "Hello, " + STRING_TO_BE_TYPED + "!";
        onView(withId(R.id.txt_show_click_result)).check(matches(withText(expectedText))); //line 3
    }

}

Line1: Enter the specified string for the control with the specified id, and then close the keyboard.
Line2: Click on the control that displays Say hello content.
Line3: Compare the control text with the specified id to match the specified text.

Asynchronous examples, from Here:

private String temp = null;

    public void testAsyncTask() throws Throwable {
        final CountDownLatch signal = new CountDownLatch(1);

        // Executing asynchronous operations in UI threads
        runTestOnUiThread(new Runnable() {

            @Override
            public void run() {
                // Executing asynchronous tasks, this is just an example, there is no actual code to run, you know.
                new MyAsyncTask() {
                    @Override
                    protected void onPostExecute(String result) {
                        super.onPostExecute(result);
                        temp = result;
                        signal.countDown();

                    }
                }.execute();
            }
        });
        signal.await();
        assertEquals("kale", temp);
    }

Personal Feeling: For the non-ui part of the test is relatively simple, writing AssertEquals can complete most of the tests; for the ui part, if the test is more troublesome, especially for some custom events, there are callback codes, even on TouchListener, which is difficult to describe. [When to press, where to press, drag speed, drag to which point? Does the display flicker during the process? This determines that there will be countless examples, unit testing should not be done. Later, I will buy a book to study specially. The logic part of non-ui will use unit testing. The logic of ui can be separated and temporarily published for unit testing.

Conclusion:

Unit testing is good for logic testing, ui is good for situation, and individual will be used for logic testing. In addition, we must control the number of method parameters, otherwise there are five parameters, even if each is boolean, there are 32 cases, hehe, kill you. It is suggested that the control should be within three.

Topics: Android Junit calculator xml