Unit testing in android studio - android-studio

I am using newest version of android studio gradle plugin 1.2.3. I am unable to understand how to create unit tests in it; all the available answers are for older version of android. Help me.

first of all you need a different folder structure for your unit tests.
android studio automatically generats the androidTest folder for instrumentation tests, but you can't put your unit tests in there. so you have to create a "test" folder:
- src
-- androidTest //for instrumentation tests
-- main //source code
-- test //for unit tests
use the same package structure for your tests as for the class you want to test.
you can switch in your build variants of android studio between Android Instrumentation Tests and Unit Tests.
depending on your selection test or androidTest folder will be show in your project tab.
finally you have to add junit to your dependencies in gradle:
dependencies {
testCompile 'junit:junit:4.12'
}
the test classes in your test folder can for example look like this:
package package.of.class.to.test
import org.junit.Before;
import org.junit.Test;
...
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
public class TestSomething{
#Before
public void setup(){
// test setup
}
#Test
public void testSomething(){
// your unit tests like these simple examples
assertThat(anyBooleanResult, is(expectedBooleanResult));
assertEquals(anyIntResult, expectedIntResult);
}
}
for further information you can also take a look on this thread.

Related

Running an instrumented test in Android Studio without simulating user actions

I have written some code that manipulates MotionEvent instances, and want to write a unit test for it.
The unit test needs to validate my manipulations only; it does not need to simulate any user actions.
I understand it needs to be an instrumented test to be able to use the methods of MotionEvent; I need the actual methods, not any mocking.
I have defined an instrumented test in the directory src/androidTest/...; however, it still throws the exception
java.lang.RuntimeException: Method obtain in android.view.MotionEvent not mocked.
My build.gradle file for the module has the following entries:
defaultConfig {
...
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
...
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
The imports in my test class are as follows:
import android.view.MotionEvent;
import org.junit.Test;
import static org.junit.Assert.*;
How can I run this test?
My mistake was as follows.
I initially thought that a local unit test would suffice, since no user action was involved.
It turned out to be wrong: the local unit tests do not get access to the Android methods.
I moved my file containing the test, to the place prescribed for the instrumented tests, /src/androidTest/java/, but did not change the file; this can be seen in my imports.
For this reason it still ran as a local non-instrumented test.
After I realized it, I changed the file to mimic the ExampleInstrumentedTest created by Android studio together with my project. I also deleted the run configuration which was still a local test.
After that Android studio prompted me to create a new run configuration, and the test ran successfully.

Android Studio 3 beta 2 ClassNotFound in kotlin unit tests

I am using Android Studio 3.0 beta 2, converted an existing project to gradle plugin 3.0.0-beta2
When I try to run an existing unit test written in kotlin I get 'java.lang.NoClassDefFoundError: com/other/domain/CollectionItem'
The test itself is very simple:
import org.junit.Test
import org.junit.Assert.*
class CollectionViewModelTest {
#Test
fun getItemsWithManyItemsWillReturnCollectionItemViewModels() {
val collectionItems = listOf(CollectionItem(42, "Item1", CollectionItemType.COLLECTION, ""), CollectionItem(43, "Item2", CollectionItemType.COLLECTION, ""), CollectionItem(44, "Item3", CollectionItemType.COLLECTION, ""))
val collection = Collection(45, "Home", "Home collection", collectionItems, 42)
val collectionViewModel = CollectionViewModel(collection)
assertTrue(collectionViewModel.items.first().isFirst)
assertFalse(collectionViewModel.items.first().isLast)
assertFalse(collectionViewModel.items[1].isFirst)
assertFalse(collectionViewModel.items[1].isLast)
assertTrue(collectionViewModel.items.last().isLast)
assertFalse(collectionViewModel.items.last().isFirst)
}
}
It works when I run it from the terminal using ./gradlew
Any ideas why this can happen?
Edit:
This seems to happen only when the test requires classes from other library projects.
In this case CollectionItem is part of another library in the same project and it's included in the gradle file via implementation project(':domain')
Edit
It might also be worth mentioning that domain module is pure java
Edit
Figured out the problem is when the library (domain) has classes written in kotlin, those classes will throw NoClassDefFoundError in unit test's only.

Is JUnit really unable to find my test class in android studio?

I read the solution to How to run a simple JUnit4 test in Android Studio 1.1? and verified my gradle plugin version is greater than 1.1
Right Clicking my junit 4 test class and selecting run gives this error in android studio:
Cannot find class com.me.android.javamodule.MyTestClass
My android proj dir looks like:
In module "app":
src-->main
src-->test-->java-->com.me.android.working contains WorkingTest.java
src-->test-->java-->com.me.android.javamodule contains MyTestClass.java
"javamodule" is a regular java module that the app module depends on, it is a sibling to the "app" module.
I don't think the error is accurate because I copied "MyTestClass.java" into com.me.android.working, which contains WorkingTest.java, a Junit4 test that CAN run. Android Studio still complains with the same error.
Here is MyTestClass.java
package com.me.android.javamodule;
import org.junit.Before;
import org.junit.Test;
public class MyTestClass {
private Solver solver;
#Before
public void init() {
solver = new Solver();
}
#Test
public void testReverse() {
assertTrue(solver.parseStr("woof").equals("foow"));
}
}
This worked for me:
right click src and select New Directory, call it test
do the same for test and call it java
right click java and select New Package to create a new package like com.application. unit test can go here.

Cucumber-jvm runner with many features, just run one

I have this project structure:
/src
/it
/java
/com/xxx/test/it
ContextSteps
/inventory
InventoryIT
InventorySteps
/resources
/com/xxx/test/it/inventory
1.feature
2.feature
Runner InventoryIT (both features are annotated with #inventory)
#RunWith(Cucumber.class)
#CucumberOptions(tags = "#inventory")
public class InventoryIT {
}
Note that ContextSteps in injected in InventorySteps through cucumber-picocontainer.
When I execute project tests through this runner (with maven or from the IDE as well), I expect both 1.feature and 2.feature run (because both are placed in the same resources package), but just runs the first one: 1.feature.
Am I missing something?
Thanks for the help.
Still wondering why is just running one of the two features... can be fixed setting manually the features resources path:
features = "src/it/resources/com/xxx/test/it/inventory")
through #CucumberOptions annotation in the InventoryIT runner.
#RunWith(Cucumber.class)
#CucumberOptions(tags = "#inventory", features = "src/it/resources/com/xxx/test/it/inventory")
public class InventoryIT {
}
Making this change, both feature run.

How do I run a task created by a plugin in gradle

I've written a gradle plugin that adds a custom task called generateTestDocs, which depends on the task groovydoc, which itself is created by the groovy plugin.
//MyPlugin.groovy
#Override
void apply(Project project) {
project.apply(plugin: 'groovy')
project.task(type: GenerateTestDocsTask, dependsOn: ':groovydoc', 'generateTestDocs')
}
project.tasks.groovydoc.doFirst {
println "I should see this message but I don't"
}
I'm trying to test this plugin by running the task generateTestDocs
#Test
void testRunGenerateTestDocs() {
Project project = ProjectBuilder.builder().build()
project.apply(plugin: 'my.gradle.plugin')
project.tasks.generateTestDocs.actions*.execute(project.tasks.generateTestDocs)
}
For the last line in my test, I'd like to instead just say project.task.generateTestDocs.execute() and have it run the task with all of its dependencies, but that doesn't seem to work. The documentation for writing gradle plugins only shows assertions like assertTrue(project.tasks.hello instanceof GreetingTask) which shows the task is added to the project, but doesn't show how to run that task.
ProjectBuilder is only meant for unit tests. To run a build as part of a test, you'll need to use the Gradle tooling API, or a third-party plugin such as nebula-test (which builds upon the tooling API).
I faced the same question, I solved this by add
apply plugin: CustomPluginName
in current gradle.build :
apply plugin: 'groovy'
...
// in this case Plugin name is MyPlugin
apply plugin: MyPlugin

Resources