Hello, has anyone achieved running Unit Test on a ...
# multiplatform
i
Hello, has anyone achieved running Unit Test on a Multiplatform lib wit OpenCV ? I keep getting this error when I add
OpenCVLoader.initLocal()
in my tests
Copy code
ImageQualityTest > testImageQuality FAILED
    java.lang.RuntimeException: Method d in android.util.Log not mocked. See <https://developer.android.com/r/studio-ui/build/not-mocked> for details.
        at android.util.Log.d(Log.java)
        at org.opencv.android.StaticHelper.initOpenCV(StaticHelper.java:18)
        at org.opencv.android.OpenCVLoader.initLocal(OpenCVLoader.java:31)
        at com.ltu.ibsalib.ImageQualityTest.testImageQuality(Test.android.kt:34)
s
Looks like OpenCV does an "android.util.Log.d(....)" call, which requires either an actual implementation (to write to log-cat) or a mock one. Did you try to do a static-mock of that method (using the mocking library that you chose)?
i
Not yet 🙂 I didn't understand OpenCV was calling
android.util.Log.d
. I guess
mockk
should do the job
s
Does opencv offer a way to replace its 'logger' with another implementation? If so, you could provide a fake logger implementation
That or use Robolectric as part of your tests, which mocks out a lot of Android specific apis.
i
I'm searching, but I don't think OpenCV provides a direct way to replace its logger. I heard about
Robolectric
but I actually have never used it
i
I'm getting the same error with this code (same for
initLocal
), any clue?
e
did you use
Copy code
@RunWith(RobolectricTestRunner::class)
?
@Config
alone does nothing without the runner
i
i finally used this: https://stackoverflow.com/a/46793567/11261546 to resolve the
log.d
problem , however, I got a different problem,
Cannot load library opencv_java4
I think this one is related to how .so and jni files are imported... the unit test don't seem to locate the right folders on
initLocal()
that way i didn't need any lib to install
e
Cannot load library
native JNI libraries for Android will not work in unit tests, because they run on the host in a non-Android environment
i
I understood that, but then what's the right way to test?
e
for opencv you may be able to forcibly load a dll/so/framework built for the host before the java library initializes, but in general: you simply cannot unit test them
i
🤔
so i'm quite new in this... but for example I have a function called
birghtness(image: Mat)
and i know that for certain image it returns
123.4
... there's no way to test this in a CI? I'd like to do it to know if a modification broke the behaviour 🤔
e
if it uses a native function, then that must be provided for the host architecture, or you cannot use it
you could use robolectric shadows to bypass the whole opencv class, but I'm not sure what you're trying to test
i
🤔 I see ... like of course there's OpenCV for Linux, but i kind of thought I could run the unit test on an android emulator
e
there are instrumented tests that run on emulators and real devices. those are different than unit tests
🤔 1
i
you could use robolectric shadows to bypass the whole opencv class, but I'm not sure what you're trying to test
Exactly, i would like to call the real openvc functions
🤔 1
> there are instrumented tests that run on emulators and real devices. those are different than unit tests oh, are those created by default? .. this may be what i need
e
if there is an opencv library for JVM with an API compatible to the opencv for Android library, you can try substituting the dependency in the unit test configuration
i
you lean something like this?
i see there's a task
./gradlew :composeApp:connectedAndroidTest
, is that what you mean with instrumented tests?
e
yes
👀 1
i
i'll check that
s
Not sure what you try to test, but don't try to test the actual OpenCV functionality itself. The authors of OpenCV already did that 😁 Instead, you could abstract the OpenCV api out into an interface - dependency inversion - and provide your own fake/dummy implementation when unit-testing (and the actual OpenCV impl for the app) - dependency injection.
i
i understand this, however, there are complex types like
Mat
which i would like to use during testing and that would be quite hard to fake
e
if there is an opencv library for JVM with an API compatible to the opencv for Android library, you can try substituting the dependency in the unit test configuration
I'm not familiar with the opencv ecosystem at all, but if it's a simple maven dependency, then you could try forcing Gradle to use a different dependency for the unit tests, e.g.
Copy code
configurations.all {
    if (name.endsWith("UnitTestRuntimeClasspath")) {
        resolutionStrategy.dependencySubstitution {
            substitute(module("opencv:opencv-android:1.0"))
                .using(module("opencv:opencv-jvm:1.0"))
                .because("host JVM compatibility")
        }
    }
}