SkillAgentSearch skills...

AndroidTestingBox

Android project to experiment various testing tools

Install / Use

/learn @RoRoche/AndroidTestingBox

README

AndroidTestingBox

Android project to experiment various testing tools. It targets Java and Kotlin languages. Priority is given to fluency and ease of use. The idea is to provide a toolbox to write elegant and intelligible tests, with modern techniques like behavior-driven testing frameworks or fluent assertions.

Android Arsenal Android Weekly Dependency Status

logo

<!-- run the following command line: markdown-toc -i README.md --> <!-- toc --> <!-- tocstop -->

AndroidTestingBox in the news

System under test (SUT)

Simple Java class

public class Sum {
    public final int a;
    public final int b;
    private final LazyInitializer<Integer> mSum;

    public Sum(int a, int b) {
        this.a = a;
        this.b = b;
        mSum = new LazyInitializer<Integer>() {
            @Override
            protected Integer initialize() throws ConcurrentException {
                return Sum.this.a + Sum.this.b;
            }
        };
    }

    public int getSum() throws ConcurrentException {
        return mSum.get();
    }
}

Android Activity

Here stands the layout file:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    android:id="@+id/activity_main"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/ActivityMain_TextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="@string/app_name"/>

    <Button
        android:id="@+id/ActivityMain_Button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/ActivityMain_TextView"
        android:layout_centerHorizontal="true"
        android:text="@string/click_me"/>
</RelativeLayout>

and here stands the corresponding Activity:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val textView: TextView = findViewById(R.id.ActivityMain_TextView) as TextView
        val button = findViewById(R.id.ActivityMain_Button)
        button.setOnClickListener({ view: View -> textView.setText(R.string.text_changed_after_button_click) })
    }
}

JUnit

Fluent assertions: truth

Alternative: AssertJ

Frutilla

@RunWith(value = org.frutilla.FrutillaTestRunner.class)
public class FrutillaSumTest {

    @Frutilla(
            Given = "two numbers a = 1 and b = 3",
            When = "computing the sum of these 2 numbers",
            Then = "should compute sum = 4"
    )
    @Test
    public void test_addition_isCorrect() throws Exception {
        given("two numbers", () -> {
            final int a = 1;
            final int b = 3;

            when("computing the sum of these 2 numbers", () -> {
                final Sum sum = new Sum(a, b);

                then("should compute sum = 4", () -> assertThat(sum.getSum()).isEqualTo(4));
            });
        });
    }
}

Fluent test method names

Specifications framework: Spectrum

import static com.google.common.truth.Truth.assertThat;
import static com.greghaskins.spectrum.Spectrum.describe;
import static com.greghaskins.spectrum.Spectrum.it;

@RunWith(Spectrum.class)
public class SpectrumSumTest {
    {
        describe("Given two numbers a = 1 and b = 3", () -> {
            final int a = 1;
            final int b = 3;

            it("computing the sum of these 2 numbers, should compute sum = 4", () -> {
                final Sum sum = new Sum(a, b);

                assertThat(sum.getSum()).isEqualTo(4);
            });
        });
    }
}

Alternative: Oleaster

Hierarchies in JUnit: junit-hierarchicalcontextrunner

@RunWith(HierarchicalContextRunner.class)
public class HCRSumTest {

    public class GivenTwoNumbers1And3 {
        private int a = 1;
        private int b = 3;

        @Before
        public void setUp() {
            a = 1;
            b = 3;
        }

        public class WhenComputingSum {
            private Sum sum;

            @Before
            public void setUp() {
                sum = new Sum(a, b);
            }

            @Test
            public void thenShouldBeEqualTo4() throws ConcurrentException {
                assertThat(sum.getSum()).isEqualTo(4);
            }
        }

        public class WhenMultiplying {
            private int multiply;

            @Before
            public void setUp() {
                multiply = a * b;
            }

            @Test
            public void thenShouldBeEqualTo3() throws ConcurrentException {
                assertThat(multiply).isEqualTo(3);
            }
        }
    }
}

Novelty to consider: JUnit 5 Nested Tests

BDD tools

Cucumber

  • Define the .feature file:
Feature: Sum computation

  Scenario Outline: Sum 2 integers
    Given two int <a> and <b> to sum
    When computing sum
    Then it should be <sum>

    Examples:
      |  a |  b | sum |
      |  1 |  3 |   4 |
      | -1 | -3 |  -4 |
      | -1 |  3 |   2 |
  • Define the corresponding steps:
public class SumSteps {
    Sum moSum;
    int miSum;

    @Given("^two int (-?\\d+) and (-?\\d+) to sum$")
    public void twoIntToSum(final int a, final int b) {
        moSum = new Sum(a, b);
    }

    @When("^computing sum$")
    public void computingSum() throws ConcurrentException {
        miSum = moSum.getSum();
    }

    @Then("^it should be (-?\\d+)$")
    public void itShouldBe(final int expected) {
        Assert.assertEquals(expected, miSum);
    }
}
  • Define the specific runner:
@RunWith(Cucumber.class)
@CucumberOptions(
        features = "src/test/resources/"
)
public class SumTestRunner {
}
  • Relevant tools:

JGiven

public class JGivenSumTest extends SimpleScenarioTest<JGivenSumTest.TestSteps> {

    @Test
    public void addition_isCorrect() throws ConcurrentException {
        given().first_number_$(1).and().second_number_$(3);
        when().computing_sum();
  
View on GitHub
GitHub Stars63
CategoryDevelopment
Updated2y ago
Forks3

Languages

Java

Security Score

85/100

Audited on Sep 8, 2023

No findings