androidkotlinandroid-testingandroid-stylesandroid-attributes

Android Testing method that returns color resource id from R.attr reference


I'm implementing AndroidInstrumentationTest for first time using Android Studio 3.2, trying to check if method returns color resource ID from attributes (R.attr and color setted in styles) depending on String, but the resource ID returned is always 0 instead of expected.

The code is working properly in my app and color is setted as this:

textView.setTextColor(fetchCorrectColor(myContext))

The problem is fetchColor from tests returns 0

Other resources as mContext.getString() works perfectly

Test class is annotated with @RunWith(AndroidJunit4::class) and running on Android Pie (28) emulated and device

I tried different context with same result:

InstrumentationRegistry.getInstrumentation().targetContext
InstrumentationRegistry.getInstrumentation().context
ApplicationProvider.getApplicationContext()

Method to test

fun getTextColor(status: String?, mContext: Context): Int{
    return when(status){
        "A", "B" ->{
            fetchCorrectColor(mContext)
        }
        "C", "D"->{
            fetchWarningColor(mContext)
        }
        else -> {
            fetchDisabledColor(mContext)
        }
    }
}

Methods to fetch color resource if from attributes

fun fetchCorrectColor(context: Context): Int{
    return fetchColor(context, R.attr.correct)
}

private fun fetchColor(context: Context, colorId: Int): Int{
    val typedValue = TypedValue()
    context.theme.resolveAttribute(colorId, typedValue, true)
    return typedValue.data
}

Test

@Test fun getTextColor_isCorrect(){
    Assert.assertEquals(R.attr.correct, getTextColor("A", mContext))
    Assert.assertEquals(R.attr.correct, getTextColor("B", mContext))
    Assert.assertEquals(R.attr.warning, getTextColor("C", mContext))
    Assert.assertEquals(R.attr.warning, getTextColor("D", mContext))
    Assert.assertEquals(R.attr.disabled, getTextColor(null, mContext))
}

This is the error that I'm getting all the time:

java.lang.AssertionError: expected:<2130968760> but was:<0>
at org.junit.Assert.fail(Assert.java:88)

Solution

  • Attributes are Theme aware. Be sure context uses same theme as your app:

    appContext.setTheme(R.style.AppTheme)
    

    Sample test code that resolves R.attr.colorPrimary attribute that's only available in AppCompat theme:

    @Test
    fun testColorPrimary() {
        // Context of the app under test.
        val appContext = InstrumentationRegistry.getTargetContext()
    
        // actual R.color.colorPrimary value
        val actualPrimaryColor = appContext.getColor(R.color.colorPrimary)
    
        // R.attr.colorPrimary resolved with invalid theme
        val colorPrimary1 = TypedValue().also {
            appContext.theme.resolveAttribute(R.attr.colorPrimary, it, true)
        }.data
    
        // provided context has invalid theme so attribute resolution fails (returns 0)
        assertEquals(0, colorPrimary1)
    
        // be sure test context uses same theme as app
        appContext.setTheme(R.style.AppTheme)
    
        // R.attr.colorPrimary resolved from valid theme
        val colorPrimary2 = TypedValue().also {
            appContext.theme.resolveAttribute(R.attr.colorPrimary, it, true)
        }.data
    
        // valid theme returns proper color
        assertEquals(actualPrimaryColor, colorPrimary2)
    }