A bunch of unit tests fails because of an empty class - android

Recently I started to observe a very strange situation:
a whole bunch of unit tests (~160 different unit tests) fails because of one empty class in directory module-name/src/test/.
This class looks in the following way:
package com.myapp.android.common.extensions
class MyExtensionsTest {
}
When I remove this class, all unit tests pass. When I remove class declaration and leave only package in the file, all unit tests pass. But as soon as I add declaration
class MyExtensionsTest {
}
to the package, this makes ~160 different unit tests fail.
And the failing tests cover code of classes that seem to be not connected to the extension file MyExtensions at all.
And all these ~160 different unit tests fail
the same way if MyExtensionsTest class contains any test methods.
What can be a reason of this behaviour?
Is there anything wrong with my unit test setup?

Related

How to set an order in instrumented test over the Test Class?

I'd like to set an order over the Test Class.
#RunWith(AndroidJUnit4::class)
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
class ATest {
#Test
fun test0000()
#Test
fun test0001()
}
#RunWith(AndroidJUnit4::class)
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
class BTest {
#Test
fun test0002()
#Test
fun test0003()
}
I'd like to test ATest.test0000 -> ATest.test0001 -> BTest.test0002 -> BTest.test0003
Because ATest class must be tested before B Test.
How can I do that? Is it possible?
Firstly, I would recommend you to not have any dependencies in Tests.
i.e. Test A class and Test B class should run independently from each other.
This really helps when your application grows.
There should not be a condition that one test should run before another.
Only in a rare / genuine scenario we should have such dependency on sequence.
Because if you design your test with sequence related dependency then it will be difficult for you to maintain your test cases and it will get difficult when you follow Test Driven Development(TDD).
For above case, please try using SuiteClasses.
The SuiteClasses annotation specifies the Suite runner which test classes to include in this suite and in which order.
Please refer to the sample provided by Junit Team HERE

Koin tests - DependencyResolutionException

I have multiple test classes with multiple tests in each class.
In each class I want to make sure that I get fresh test dependencies for each test. So I prepare my tests like this:
#Before
fun initTest() {
loadKoinModules(listOf(module {
scope(TEST_SCOPE, override = true) { Dependency1() }
scope(TEST_SCOPE, override = true) { Dependency2() }
}))
getKoin().createScope(TEST_SCOPE)
}
#After
fun shutdown() {
getKoin().getScope(TEST_SCOPE).close()
}
And it works very well when I run only the tests in that particular test class.
But when I run all my tests in the same time, and if multiple test classes have the same dependencies in their modules, I get an Exception like this:
org.koin.error.DependencyResolutionException: Multiple definitions found - Koin can't choose between :
Scope [name='Dependency2',class='package.Dependency2']
Scope [name='Dependency2',class='package.Dependency2']
Check your modules definition, use inner modules visibility or definition names.
So I fixed this by simply calling stopKoin() at the end of my shutdown method.
And so far I haven't noticed that my tests run much slower. So basically my question is: is this the preferred way to use Koin in my tests? Am I missing something or not using Koin Properly ?
I realize that this is more a code review/advice question than a real problem but I think this might still be useful to others.
Thanks

AndroidJunit4 doesn't accept space function test name?

I have the following test, where the test name is with space and backtick for my instrumental test
#RunWith(AndroidJUnit4::class)
class MyTestClass {
#Rule
#JvmField
var activityRule: ActivityTestRule<MainActivity> = ActivityTestRule(MainActivity::class.java)
#Test
fun `My space name testing`() {
// Some test
}
}
However when running it, it can't be executed (i.e. No test were found)
Checking on it, I saw this linting error on the test function name..
This inspection reports identifiers in android projects which are not accepted by the Android runtime (for example, method names containing spaces)
When I rename my test function from My space name testing to mySpaceNameTesting, the test run.
Is it really that AndroidJunit4 runtime can't support test function name with spaces?
Correct, it's unsupported in the Android runtime. See the Coding Conventions page here. Specifically:
In tests (and only in tests), it's acceptable to use method names with
spaces enclosed in backticks. (Note that such method names are
currently not supported by the Android runtime.) Underscores in method
names are also allowed in test code.

Integrating Robolectric and Cucumber

I want to combine both Robolectric and Cucumber (JVM).
Currently I have two classes ActivityStepdefs where two step definitions for activity management are defined.
My second class is RoActivity Where for example an activity is created from it's class name, and where Robolectric will be used.
When I run RoActivityTest using RobolectricTestRunner the test in this class passes, but when I run RunCukesTest (class for running features as junit test) the code from RoActivity is not running as part of Robolectric, i.e. RunCukesTest search for features on my project and match it with a method inside ActivityStepdefs and finally this class will call a method from RoActivity
Is possible to run test with both junit both* runners?
I'm not sure but perhaps it's possible to do something like powermock, using junit rules.
In that case for which one should I have to define the rule?
*Cucumber and Robolectric
My small 5 cents.
Cucumber is mostly used for acceptance tests (correct me if you use it for unit testing) and Robolectric is mostly used for unit testing.
As for me, it is overkill to write cucumber during TDD. And Robolectric is still not android and I would run acceptance tests on real device or at least emulator.
I'am facing the same problem, after some google work, I got a solution:
#RunWith(ParameterizedRobolectricTestRunner::class)
#CucumberOptions( features = ["src/test/features/test.feature","src/test/features/others.feature"], plugin = ["pretty"])
class RunFeatures(val index: Int, val name:String) {
companion object {
#Parameters(name = "{1}")
#JvmStatic
fun features(): Collection<Array<Any>> {
val runner = Cucumber(RunFeatures::class.java)
Cucumber()
val children = runner.children
return children.mapIndexed{index, feature ->
arrayOf(index,feature.name)
}
}
}
#Test
fun runTest() {
val core = JUnitCore()
val feature = Cucumber(RunFeatures::class.java).children[index]!!
core.addListener(object: RunListener() {
override fun testFailure(failure: Failure?) {
super.testFailure(failure)
fail("$name failed:\n"+failure?.exception)
}
})
val runner = Request.runner(feature)
core.run(runner)
}
}
but seems not an pretty solution for me, can somebody help me out these problem:
must explicitly list all feature file path. but cannot use pattern such as *.feature
when failed cannot know which step failed.
parameter can only pass primitive type data,
I've get into cucumber source , but seems CucumberOptions inline Cucumber , I cannot pass it programmatically but can only use annotation .

android instrumentation testsuite

I have written two test cases in a package com.app.myapp.test
When I try to run them both of them are not getting executed, only one test case gets executed and stops.
I have written the following testsuite in the same package
AllTests.java
public class AllTests extends TestSuite {
public static Test suite() {
return new TestSuiteBuilder(AllTests.class).includePackages("./src/com.ni.mypaint.test","./src/com.ni.mpaint.test").build();
/* .includeAllPackagesUnderHere()
.build();*/
}
Is the code and location for this testsuite is correct?
Well, certainly leave off the '/src/' portion of the package listing for that invocation. Either way, the easiest and most flexible way to run your tests this is to make sure all your tests are in a subpackage of where AllTests is (e.g. com.app.myapp.test.tests) and use this for the suite:
public static Test suite() {
return new TestSuiteBuilder(AllTests.class)
.includeAllPackagesUnderHere().build();
}
Make sure your tests run individually, too, without the suite runner -- the suite won't pick up your tests if they're set up wrong to begin with.
(This is better than explicitly listing the package name since it's more portable -- you can rename your test package without breaking it, for example.)

Categories

Resources