Reputation:
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
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=
Run mvn test
, it passes
Switch to French locale with OS X GUI
Run mvn test
, it fails (as expected)
Run locale
in the same terminal - it still produces the same results as before (although it shouldn't, as I switched to French)
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
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