Provide a Rule for overriding app locale in instrumented tests
Please provide a standard way to override the app's Locale in tests. Main use cases for me are testing against a given language translation, and for tests on screens that display currency amount where the format depends on your locale, eg:
- en_US displays
GBP2.00 - en_GB displays
£2.00
so I need to set a locale to make sure my UI assertions match the locale-dependent text.
I currently use
class LocaleOverrideRule(
private val getLocale: () -> Locale,
) : ExternalResource() {
private lateinit var previousLocale: Locale
override fun before() {
previousLocale = Locale.getDefault()
val newLocale = getLocale()
Locale.setDefault(newLocale)
// We also have to update Locale in the Configuration, otherwise Locale.setDefault() gets
// overwritten with Configuration.locale's value at startup.
val resources: Resources = InstrumentationRegistry.getInstrumentation().targetContext.resources
val config: Configuration = resources.configuration
config.setLocale(newLocale)
resources.updateConfiguration(config, resources.displayMetrics)
println("Setting locale from $previousLocale to ${Locale.getDefault()}")
println("Format locale is now ${Locale.getDefault(Locale.Category.FORMAT)}")
}
override fun after() {
println("Restoring locale from ${Locale.getDefault()} to $previousLocale")
Locale.setDefault(previousLocale)
}
}
which works, but it relies on the deprecated Resources.updateConfiguration(). It recommends replacing that with Context.createConfigurationContext(Configuration) but I don't see an obvious way to provide a context that the ActivityScenario should use. The upcoming AppCompatDelegate.setAppLocales() may work for this purpose.
Either way, I feel like this is stuff is hard enough to work out that AndroidX test should provide a built-in solution.
Same problem gere, but i've fond another solution. AppCompatDelegate.setAppLocales() and LocalManager not working (recreate activity while testing, not good 😄 )
So i use a Restricted API
@SuppressLint("RestrictedApi")
@Before
fun configureLanguage() {
val locales = LocaleListCompat.forLanguageTags("fr").toLanguageTags()
AppLocalesStorageHelper.persistLocales(context, locales)
}
PS: Why ? Because with per app language implementation, your solution don't work for me.
PS2: unfortunately, this method create a double launch of my activity under testing ...