Skip to content

Commit

Permalink
- added unit tests for the library
Browse files Browse the repository at this point in the history
- extended the test coverage task to include the coverage from unit tests
  • Loading branch information
Piotr Zawadzki committed Oct 18, 2016
1 parent 12f93ff commit 89cf31b
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 8 deletions.
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,10 @@ and also declared when building the activity chooser:
```

## Testing
### Basic info
The library is tested with Espresso + Cucumber. To run the tests you need to execute:
The library is tested mainly with Espresso + Cucumber as well as a few unit tests.

### Instrumentation tests
To run instrumentation tests you need to execute:

```bash
./gradlew connectedDebugAndroidTest
Expand All @@ -209,16 +211,23 @@ This additionally fetches the Cucumber reports from the device and saves them to

It is also recommended to install _Cucumber for Java_ and _Gherkin_ plugins in Android Studio for better Cucumber integration inside of the IDE.

### Unit tests
To run unit tests you need to execute:

```bash
./gradlew testDebugUnitTest
```

### Code coverage
Tests can be also executed with code coverage. To do so execute:

```bash
./gradlew jacocoTestReport
```

The coverage report can be then found at ```sample/build/reports/jacoco```.
The coverage report can be then found at ```sample/build/reports/jacoco```. This task cleans the project, runs the unit tests & instrumentation tests and at the end it creates the report.

### Running selected scenarios only
### Running selected scenarios only for instrumentation tests
All the tested scenarios have Cucumber tags. You can run a specific test by using this tag.
Assuming you wanted to run only the scenario with tag _@sample-scenario-22_ you would do the following:

Expand Down
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ configure(allprojects) {
androidSupportLibraryVersion = "24.2.1"
butterknifeVersion = "8.4.0"

junitVersion = "4.12"
mockitoVersion = "1.10.19"
robolectricVersion = "3.1.2"

runnerVersion = "0.6-alpha"
rulesVersion = "0.6-alpha"
espressoVersion = "2.3-alpha"
Expand Down
15 changes: 15 additions & 0 deletions material-activity-chooser/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ android {
sourceSets.all { sourceSet ->
sourceSet.res.srcDirs += ['src/main/res-public']
}

testOptions {
//workaround so that code coverage is working with Robolectric: http://stackoverflow.com/a/35769943/973379
unitTests.all {
jacoco {
includeNoLocationClasses = true
}
}
}
}

dependencies {
Expand All @@ -61,6 +70,12 @@ dependencies {
compile ("com.android.support:recyclerview-v7:$androidSupportLibraryVersion")
compile ("com.android.support:design:$androidSupportLibraryVersion")

testCompile("junit:junit:$junitVersion")
testCompile("org.mockito:mockito-core:$mockitoVersion")
testCompile("org.robolectric:robolectric:$robolectricVersion") {
exclude group: 'commons-logging', module: 'commons-logging'
exclude group: 'org.apache.httpcomponents', module: 'httpclient'
}
}

gradle.taskGraph.beforeTask { Task task ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,10 @@ public void show() {
Log.w(TAG, "Removing package '" + packageName + "' since its secondary intent is incompatible with the main intent!");
}
}
if (!secondaryIntentsForPackages.isEmpty()) {
materialShareIntent.putExtra(MaterialActivityChooserActivity.SECONDARY_INTENTS_KEY, secondaryIntentsForPackages);
}

materialShareIntent.putExtra(MaterialActivityChooserActivity.SECONDARY_INTENTS_KEY, secondaryIntentsForPackages);
}
mContext.startActivity(materialShareIntent);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package com.github.zawadz88.activitychooser;

import android.content.Context;
import android.content.Intent;
import android.os.Build;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;

/**
* @author Piotr Zawadzki
*/
@RunWith(RobolectricTestRunner.class)
@Config(sdk = Build.VERSION_CODES.LOLLIPOP, manifest = Config.NONE)
public class MaterialActivityChooserBuilderTest {

private static final String SOME_INTENT_ACTION = "some_intent_action";

private static final String SOME_OTHER_INTENT_ACTION = "some_other_intent_action";

private static final String SOME_PACKAGE = "some package";

@Mock
Context mockContext;

@Mock
Intent mockIntent;

@Mock
Intent mockSecondaryIntent;

@Captor
ArgumentCaptor<Intent> intentArgumentCaptor;

MaterialActivityChooserBuilder builder;

@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
builder = new MaterialActivityChooserBuilder(mockContext);
}

@Test
public void should_not_start_activity_if_intent_not_provided() {
//when
builder.show();

//then
verifyZeroInteractions(mockContext);
}

@Test
public void should_not_start_activity_if_intent_action_not_provided() {
//given
builder.withIntent(mockIntent);

//when
builder.show();

//then
verifyZeroInteractions(mockContext);
}
@Test
public void should_not_pass_secondary_intents_to_activity_if_packages_array_is_empty() {
//given
doReturn(SOME_INTENT_ACTION).when(mockIntent).getAction();
builder
.withIntent(mockIntent)
.withSecondaryIntent(mockSecondaryIntent);

//when
builder.show();

//then
verifyActivityStarted();
assertThatSecondaryIntentsWereNotPassedToActivity();
}

@Test
public void should_not_pass_secondary_intents_to_activity_if_packages_array_contains_empty_strings_only() {
//given
doReturn(SOME_INTENT_ACTION).when(mockIntent).getAction();
builder
.withIntent(mockIntent)
.withSecondaryIntent(mockSecondaryIntent, "");

//when
builder.show();

//then
verifyActivityStarted();
assertThatSecondaryIntentsWereNotPassedToActivity();
}

@Test
public void should_not_pass_secondary_intents_to_activity_if_secondary_intent_has_different_action() {
//given
doReturn(SOME_INTENT_ACTION).when(mockIntent).getAction();
doReturn(SOME_OTHER_INTENT_ACTION).when(mockSecondaryIntent).getAction();
builder
.withIntent(mockIntent)
.withSecondaryIntent(mockSecondaryIntent, SOME_PACKAGE);

//when
builder.show();

//then
verifyActivityStarted();
assertThatSecondaryIntentsWereNotPassedToActivity();
}

@Test
public void should_pass_secondary_intents_to_activity_if_packages_array_contains_non_empty_strings() {
//given
doReturn(SOME_INTENT_ACTION).when(mockIntent).getAction();
doReturn(SOME_INTENT_ACTION).when(mockSecondaryIntent).getAction();
builder
.withIntent(mockIntent)
.withSecondaryIntent(mockSecondaryIntent, SOME_PACKAGE);

//when
builder.show();

//then
verifyActivityStarted();
assertTrue("Should contain the secondary intents extra", intentArgumentCaptor.getValue().hasExtra(MaterialActivityChooserActivity.SECONDARY_INTENTS_KEY));
}

private void assertThatSecondaryIntentsWereNotPassedToActivity() {
assertFalse("Should not contain the secondary intents extra", intentArgumentCaptor.getValue().hasExtra(MaterialActivityChooserActivity.SECONDARY_INTENTS_KEY));
}

private void verifyActivityStarted() {
verify(mockContext).startActivity(intentArgumentCaptor.capture());
}
}
1 change: 1 addition & 0 deletions sample/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ android {
//add all permissions on install so that there's WRITE_STORAGE permission needed for storing Cucumber reports
installOptions "-g", "-r"
}

}

dependencies {
Expand Down
8 changes: 5 additions & 3 deletions sample/code_coverage.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ tasks.whenTaskAdded { task ->
}
}

task jacocoTestReport(type:JacocoReport, dependsOn: 'connectedDebugAndroidTest') {
task jacocoTestReport(type:JacocoReport, dependsOn: [':material-activity-chooser:clean', 'clean', ':material-activity-chooser:testDebugUnitTest', 'connectedDebugAndroidTest']) {

group = 'Reporting'

Expand All @@ -47,8 +47,10 @@ task jacocoTestReport(type:JacocoReport, dependsOn: 'connectedDebugAndroidTest')
sourceDirectories = files([mainSrc, libSrc])
classDirectories = files([debugTree, libraryDebugTree])

executionData = fileTree(dir: project.projectDir, includes:
['**/*.exec', '**/*.ec'])
def androidTestExecutionData = fileTree(dir: project.projectDir, includes: ['**/*.exec', '**/*.ec'])
def unitTestExecutionData = fileTree(dir: project.parent.childProjects['material-activity-chooser'].projectDir, includes: ['**/*.exec', '**/*.ec'])

executionData = files ([androidTestExecutionData, unitTestExecutionData])

reports {
xml.enabled = false
Expand Down

0 comments on commit 89cf31b

Please sign in to comment.