In iOS there exists a tear block you can add to individual tests called addTearDownBlock and you put it inside a single test and it will only execute for that single test.
Does android have a similar version of this?
Unit testing in android is done with xUnit variation known as JUnit. If you are using JUnit 4.0, then use the following annotation:
#AfterClass //Will only execute once after all the tests in the class have exhausted
#After //Will run after every test
If you are using JUnit 5.0 then use the following annotation:
#AfterEach //Will run after every test
#AfterAll //Will only execute once after all the tests in the class have exhausted
Related
Hi I am trying to run a basic JUnit test in Android Studio. When I click run it is terminated every time before getting results. I never get pass or fail and the system does not try any other test cases.
Here are the pictures. I would like to know why it isn't working so I can keep practicing.
You can try a couple of things
Decorate your test class with #SmallTest
// #RunWith is required only if you use a mix of JUnit3 and JUnit4.
#RunWith(AndroidJUnit4::class)
#SmallTest
class ExampleInstrumentedTest {
}
Try to run your test from the command line:
./gradlew connectedAndroidTest
I have written multiple test methods in a single android instrumented test class, when I am trying to run a single test method it will run all methods exists in that class.
I want to run only one.
Earlier I was able to run all, but somehow configuration settings have been changed
class HistoryTest{
#Test
fun openHistoryTest{
}
#Test
fun closeHistoryTest{
}
#Test
fun editHistoryTest{
}
}
I want to run a specific single test method say openHistoryTest.
Currently getting an error - the command line is too long shorten the command line for test "testname"
I updated Android Studio to canary and can run the whole class or a single method as instrumental test. Currently using AS 3.6 Canary 12.
Still doesn't work on Android Studio 3.5. I can't run each method as an
instrumental test, only the whole class.
This simple test
#RunWith(JUnit4::class)
class Test {
#Test
fun test() {
assert(false)
}
}
Unexpectedly, this passes when put in androidTest (both through Android Studio and in the terminal), but obviously fails as expected when put in test.
You need to use JUnit assertions for running tests. The base assert() functionality is normally disabled when running "production" code, so you cannot depend that a plain assert statement will throw an assertion exception.
Use:
org.junit.Asserts.assertTrue( false )
to make the test fail properly.
I've got a couple of AndroidTestCase subclasses in separate packages of my project:
However, whenever I run Android Tests configuration from Android Studio, I see that my regular app is starting as well. I see that the onCreate method is fired up inside my Application class (which is really bad since I am loading some additional resources there).
Why is Android Studio/gradle running my app as well? Can I programatically detect if I am inside test or regular configuration? Can I stop my regular app from being booted before running tests?
In addition, when I am running tests in debug mode it doesn't stop on breakpoints placed inside the application's onCreate method. Why is this happening?
Edit:
Body of test class doesn't really matter, it can be something like:
public class SimpleTest extends AndroidTestCase {
public void testSample()
{
assertEquals(true, false);
}
}
Executing only this simple test fires up onCreate method inside application class.
Gradle console prints out:
Executing tasks: [:app:assembleDebug, :app:assembleDebugTest]
I guess that first task creates instance of my Application class - is it expected behavior?
Why is Android Studio/gradle running my app as well?
Can I stop my regular app from being booted before running tests?
AndroidTestCase is extension of JUnit TestCase which is aware of your android application. In case you don't need to test your android application and want to test plain java only you should use JUnit framework. Create regular JUnit tests, do not use android classes there and run JUnit test configuration like this:
You should treat AndroidTestCase as instrumentation tests which will build android app and run that tests on it. This is usefull with combination of Espresso and Robotium. Both are working on top of base android test classes and both will build and run your application before testing it. Real device or emulator is needed.
Use plain JUnit tests or Robolectric to test java on your desktop JVM.
Can I programatically detect if I am inside test or regular configuration?
You can use power of gradle to provide such info with autogenerated BuildConfig file.
At your build.gradle
android {
defaultConfig {
testPackageName "com.foo.test"
}
}
At your code:
BuildConfig.PACKAGE_NAME.equals("com.foo.test")
The AndroidTestCase is an unit test that unfortunately runs on the device (either virtual or real).
I think what you want to have is a UnitTestFramework that runs in the JVM (local on your machine). The TestFramework Robolectric can do this.
I have started a gitHub project to show how to setup the gradle test file and the project structure if you want to have UnitTests and InstrumentationTests side by side. If you want to look its AndroidGradleTests
When I create parameterized test cases in JUnit 3.x, I usually create a TestSuite with something like
public static Test suite() {
TestSuite s = new TestSuite();
for (int i = MIN; i < MAX; ++i) {
s.addTest(new MyTest(i));
}
}
This suite() method is called correctly when running JUnit from a desktop command-line. When I tried this with my Android test project, the tests don't run. How do I get my tests to run on the emulator? Or is there a different way to create parameterized tests for Android?
More thoughts:
Typically I run my tests with the command line:
adb shell am instrument -w [-e class <fully qualified test class name>[#<test method name>()]] <Android package name>/android.test.InstrumentationTestRunner
This allows me to select which tests to run from my test suite. Ideally, I want to run the the parameterized tests in this way as well. The link in the comment from #Appu describes building a separate app that runs JUnit tests. As part of that, this app has a custom TestRunner. I can very likely borrow these ideas to create a TestRunner which I can use in place of android.test.InstrumentationTestRunner. This seems like a lot of work for a not uncommon task. I prefer not to reinvent the wheel if there is already a similar solution in the Android API. Does anyone know of such a thing? Also, other alternative solutions will be helpful.
Nevermind, it looks like #dtmilano already posted this as an answer...
You can implement a test runner to be able to pass parameters to Android tests.
See the example at how to pass an argument to a android junit test (Parameterized tests).
Or is there a different way to create parameterized tests for Android?
We (Square) wrote a library called Burst for this purpose. If you add enum parameters in your test constructor, Burst's test runner will generate a test for each combination of enum values. For example:
public class ParameterizedTest extends TestCase {
enum Drink { COKE, PEPSI, RC_COLA }
private final Drink drink;
// Nullary constructor required by Android test framework
public ConstructorTest() {
this(null);
}
public ConstructorTest(Drink drink) {
this.drink = drink;
}
public void testSomething() {
assertNotNull(drink);
}
}
Quite a while after originally writing this question, I discovered that I can directly run a test class which contains a static suite() method:
adb shell am instrument -w -e class <fully qualified test class name> <Android package name>/android.test.InstrumentationTestRunner
However, the test suite doesn't run when I try to run all the tests in a given package.
Of course, this has been a while. Now I am using Android Studio instead of the command-line. I can still run the test class individually, but it still doesn't run when I select a package or try to run all of my tests.
A potential alternative is to write a master test class with a suite() method which adds all the tests to the returned TestCase. Unfortunately, this requires some manually editing every time I add a new test class to my suite.