On Thu, 17 Nov 2022 16:59:09 GMT, Lukasz Kostyra <d...@openjdk.org> wrote:

> The change moves Locale setting in the test to `@BeforeClass` and 
> `@AfterClass` calls. `@BeforeClass` method call stores current default VM 
> locale and applies Locale.US, while `@AfterClass` method restores old VM 
> locale after all tests are completed.
> 
> I tested it both on Mac and Windows, in both cases Locale is changed, 
> restored properly and tests pass.

After implementing CR fixes it turned out that these tests started to fail at 
random. Upon more investigation it turned out that the order in which JUnit 
calls test methods matters a lot. In general:
1. `@Parametrized.Parameters`-tagged methods are grouped and called first in an 
undefined moment, before any test class is executed
2. Then the order is more expected and predictable; for each test class JUnit 
calls: `@BeforeClass`, constructor, `@Before`, test, `@After`, ..., 
`@AfterClass`.

Additionally, Test Class order is selected at random.

That means that modifying a VM-wide setting like Locale cannot reside in 
`@Parametrized.Parameters` method or in static initializer block. When I added 
Locale change in all `Local*StringConverterTest` test classes, during step 1. 
one test captured machine's default Locale and changed it to en-US, while other 
tests captured previously set en-US Locale and set it again to en-US. Then 
JUnit progresses into step 2 and executes each test class, so once a test class 
completes, it might happen to be the one that captured machine's default 
Locale. It will revert Locale for other tests, effectively breaking them.

I had to refactor initialization code for these tests in order to resolve all 
problems and make them more independent. In short:
- Locale change has to be done in `@BeforeClass`-tagged static method
- Locale revert has to happen in `@AfterClass`-tagged static method
- `DateTimeFormatter` instances have to be created after Locale is set, also in 
`@BeforeClass` method
- `Local*StringConverter` classes that are checked by these tests have to be 
allocated afterwards, as they are also depending on set Locale and sometimes on 
`DateTimeFormatter` instances created earlier.
- Test also acquired Format Locale for further use, so that part had to be 
moved after Locale setup as well.
- As all these fields (like `Local*StringConverter` instance or current format 
`Locale`) are members of the test class, they must be setup somewhere after 
`@BeforeClass` method. The best spot I had for these is a `@Before`-tagged 
method.

The solution I made does not feel the most convenient but with above 
constraints it was difficult to come up with anything cleaner/less intrusive. 
This might also be a side-effect of me not knowing a mechanism in JUnit that 
could help us in such situation, so if there are any bits worth looking into 
I'd be happy to add them and simplify this change a bit.

-------------

PR: https://git.openjdk.org/jfx/pull/954

Reply via email to