user4925383
user4925383

Reputation:

Unit Testing and Mac OS X 10.10.3 Language and Region Settings

THE CASE

Without going much into details, mvn test fails on system with French language settings. In order to target that issue with regression testing, I want to create a regression test, which sets locale to French, and the runs unit tests with Maven.

I switch between English and French in System Preferences > Language & Region > Advanced > Format language.

THE PROBLEM

  1. While on English locale, I check the settings with locale:
LANG="en_GB.UTF-8"
LC_COLLATE="en_GB.UTF-8"
LC_CTYPE="en_GB.UTF-8"
LC_MESSAGES="en_GB.UTF-8"
LC_MONETARY="en_GB.UTF-8"
LC_NUMERIC="en_GB.UTF-8"
LC_TIME="en_GB.UTF-8"
LC_ALL=
  1. Run mvn test, it passes

  2. Switch to French locale with OS X GUI

  3. Run mvn test, it fails (as expected)

  4. Run locale in the same terminal - it still produces the same results as before (although it shouldn't, as I switched to French)

  5. Open new terminal and run locale:

LANG=
LC_COLLATE="C"
LC_CTYPE="UTF-8"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=

THE FINDINGS

For some reason, output of locale command corresponds to locale settings as of the time when the terminal was started. If you open up terminal, change locale via GUI and then run locale command, which won't be visible to this command.

Subsequently, if I amend locale by exporting LC_ALL or other variables of that kind, this does not actually change unit test results. If I change locale via GUI, it will.

THE QUESTION

How to change locale using command line, so that they are actually applied?

Upvotes: 1

Views: 449

Answers (1)

beresfordt
beresfordt

Reputation: 5222

You can set the locale which is used by DecimalFormat in a number of ways.

You can set the Locale returned by Locale.getDefault (which is used in DecimalFormat) by specifying some config to surefire in your pom. This would allow you to, for example, have several profiles each testing a different locale.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <argLine>-Duser.language=fr -Duser.region=FR</argLine>
    </configuration>
</plugin>

Or you could set what Locale.getDefault will return in your tests. In the below example there is a @Before/@After to revert the Locale.getDefault to its previous state so that the changing of defaultLocale does not impact other tests

public class LocaleTest {

    private Locale localeBefore;

    @Before
    public void setUp() {
        localeBefore = Locale.getDefault();
    }

    @After
    public void revertLocale() {
        Locale.setDefault(localeBefore);
    }

    @Test
    public void passesInFRFRLocale() {
        Locale.setDefault(Locale.FRANCE);
        assertThat(DecimalFormat.getInstance().format(1000.01D), is(equalTo("1 000,01")));
    }

    @Test
    public void passesInENGBLocale() {
        Locale.setDefault(Locale.UK);
        assertThat(DecimalFormat.getInstance().format(1000.01D), is(equalTo("1,000.01")));
    }
}

Upvotes: 0

Related Questions