JUnit tests always pass when executing in device - android

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.

Related

Simple JUnit test not working in Android Studio

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

Issues using custom testInstrumentationRunner

I've not found any post on Stack Overflow that helped, so I'm posting my own question.
I have a custom testInstrumentationRunner that when set doesn't run any tests.
The logs says:
App restart successful without requiring a re-install.
Running tests
adb shell am instrument -w -m --no-window-animation -e debug false -e class 'com.my.app.MyFragmentTest' com.my.app.debug.test/com.my.app.CustomTestRunner
Connected to process on device
When running the normal androidx.test.runner.AndroidJUnitRunner the tests run, but fail, because I need the custom runner.
The runner is set up like the androidx one, in:
defaultConfig {
// testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner
testInstrumentationRunner "com.my.app.CustomTestRunner"
}
It's also located in the com.my.app package in androidTest-folder
The code for the runner is:
package com.my.app
import ...
class CustomTestRunner: AndroidJUnitRunner() {
override fun newApplication(cl: ClassLoader?, className: String?, context: Context?): Application {
DexOpener.install(this)
Timber.i("This should print hopefully")
return super.newApplication(cl, ApplicationTest::class.java.canonicalName, context)
}
}
Not sure if it matters, but here's the code for the application class, which extends the application class used for the app itself:
package com.my.app
class ApplicationTest: MyApplication() {
override fun onCreate() {
super.onCreate()
appContext = applicationContext
initializeDependencyInjection()
}
override fun initializeDependencyInjection() {}
}
I have a test-case I'm trying to run, which contains 7 tests. The androidx runner fails on 7/7 tests. But when I run with the custom runner, I get duration 0ms and 0/0 tests.
So it seems like Android isn't detecting this runner. I also get the same results using a random name in the testInstrumentationRunner, like testInstrumentationRunner "not.a.TestRunner"
I'm sure you've already solved the issue or switched jobs to growing potatoes or something more productive, but I just spent my whole morning debugging this same exact scenario and managed to find a solution:
The custom instrumentation runner you have is not ignored, but there is something broken in your custom Test Application initialization. Probably in your replacement dependency injections, like it was in my case. When you run the tests using the custom runner, the custom Test Application silently crashes immediately, but this is not indicated in the test results or in any other easily visible place. The crash stack trace is, however, accessible in logcat. So solve that first, and then try using your custom test runner again.
Do not mix between Instrumentation Tests and Unit Tests:
Unit Tests
Unit tests runs in local JVM and minimizes the execution time.
Unit Tests cannot test UI of the app without mocking activity objects.
Unit test are used for white box testing for testing code.
Most of the time Unit Tests are written by Developers.
You don’t need a device connected for execution of Unit Tests.
Instrumentation Tests
Instrumentation tests are used for black box testing.
It is used to test GUI of the application along with its functionality in real environment.
For execution of Instrumentation tests you need a device /emulator on which the application is first installed and then tests are executed.
Automation Testers are involved in writing instrumentation framework.
When testing a library module, you can link the test application in src/androidTest/AndroidManifest.xml:
<manifest
xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:name="com.my.app.ApplicationTest"/>
</manifest>

Add teardown block for single test in Android

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

How to run single test method in android instrumented test class and how to change edit configuration for this

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.

In Android Kotlin, the assertNotNull causes the unit test to not run

In Android Studio I created androidTest package and added a TestClass.
The #BeforeClass function is required to be static,
so I have to add #JvmStatic and put it in the companion object.
But if put assertNotNull() inside the companion object it will show “Empty test suite” when running the test, and the test does not run.
But it does see the "+++ +++ initBeforeTest()" log which is placed before the assertXXX statement.
+++ +++ initBeforeTest()
++ +++ afterTest()
Client not ready yet..
Started running tests
Tests ran to completion.
Empty test suite.
If I comment out the assertNotNull() in the #BeforeClass function, which is inside the companion, the test will run as expected.
+++ +++ initBeforeTest()
++ +++ afterTest()
Client not ready yet..
Started running tests
java.lang.AssertionError: test assertNotNull
at org.junit.Assert.fail(Assert.java:88)
Any idea why the assertNotNull() (actually all assertXXX functions) causes the test not to run?
Gradle has:
testImplementation "junit:junit:4.12”
androidTestImplementation "com.android.support.test:runner:1.0.1”
test class:
#RunWith(AndroidJUnit4::class)
class TestClass {
companion object {
#BeforeClass #JvmStatic
fun beforeTest() {
Log.e("+++","+++ +++ initBeforeTest()")
// if comment out this assertNotNull(), the test will run
assertNotNull("test assertNotNull", null) //<== causes "Empty test suite."
}
#AfterClass #JvmStatic
fun afterTest() {
}
}
#Test
fun test1() {
assertNotNull("test assertNotNull", null)
}
}
Keep in mind that if the method you've annotated with #BeforeClass fails, the Junit Runner will not execute the rest of the suite.
Because your assertion (assertNotNull("test assertNotNull", null)) fails, an exception is thrown (actually an AssertionError) causing the suite setup to fail. This in turn causes the test runner to assume it has no tests. That's why removing the failing assertion will cause the tests to run (because the setup succeeds).
If you change your assertion in the setup to this, I suspect it will pass:
assertNull("test assertNull", null)
Edit: To be more clear, when you use assertNotNull you are telling Junit that the value provided cannot be null, and in your case it is. The first argument to assertNotNull ("test assertNotNull") is a message that will be incorporated into the failure message (as you can see in the output you've provided). The second argument (null, in this case) is the thing that cannot be null.

Categories

Resources