Rgfvfk Iff
Rgfvfk Iff

Reputation: 1609

Android change locale for tests

I want to test whether the strings are updated correctly when the user changes the language. I am using Espresso to test whether the string matches the correct locale and I am currently changing it like so:

private fun changeLocale(language: String, country: String) {
    val locale = Locale(language, country)
    Locale.setDefault(locale)
    val configuration = Configuration()
    configuration.locale = locale
    context.activity.baseContext.createConfigurationContext(configuration)


    getInstrumentation().runOnMainSync {
        context.activity.recreate()
    }

}

The problem is that the espresso test onView(withText(expected)).check(matches(isDisplayed())) is asserting false so I was wondering what is the correct way to set the default locale before running a test?

Upvotes: 4

Views: 6117

Answers (3)

Per Christian Henden
Per Christian Henden

Reputation: 1585

Kotlin version, based on the post from @Adib Faramarzi

    private fun setLocale(language: String, country: String) {
       val locale = Locale(language, country)
       // here we update locale for date formatters
       Locale.setDefault(locale)
       // here we update locale for app resources
       val context: Context = getApplicationContext()
       val res: Resources = context.resources
       val config: Configuration = res.configuration
       config.setLocales(LocaleList(locale))
       res.updateConfiguration(config, res.displayMetrics)
}

Upvotes: 1

ericn
ericn

Reputation: 13103

In my experience, setting locale at runtime is simply not reliable. This guy has a lot more to say about the topic here: https://proandroiddev.com/change-language-programmatically-at-runtime-on-android-5e6bc15c758

You should try using Firebase Test Lab or similar services and run your tests on different devices (which have different locales set)

Upvotes: 1

Adib Faramarzi
Adib Faramarzi

Reputation: 4064

according to this answer, you can change the Locale programmatically:

public class ResourcesTestCase extends AndroidTestCase {

    private void setLocale(String language, String country) {
        Locale locale = new Locale(language, country);
        // here we update locale for date formatters
        Locale.setDefault(locale);
        // here we update locale for app resources
        Resources res = getContext().getResources();
        Configuration config = res.getConfiguration();
        config.locale = locale;
        res.updateConfiguration(config, res.getDisplayMetrics());
    }

    public void testEnglishLocale() {
        setLocale("en", "EN");
        String cancelString = getContext().getString(R.string.cancel);
        assertEquals("Cancel", cancelString);
    }

    public void testGermanLocale() {
        setLocale("de", "DE");
        String cancelString = getContext().getString(R.string.cancel);
        assertEquals("Abbrechen", cancelString);
    }

    public void testSpanishLocale() {
        setLocale("es", "ES");
        String cancelString = getContext().getString(R.string.cancel);
        assertEquals("Cancelar", cancelString);
    }

}

you can easily convert that code to Kotlin.

Upvotes: 6

Related Questions