Testing a Locale with custom grouping separator

My app processes numbers, and depends on the grouping separator on the system locale (Locale.current).

The user can set a completely custom symbol as their number separator in the macOS System Preferences.

In my tests, I need to verify that custom grouping separators on Locale objects work correctly. But I can't set a custom grouping separator as the groupingSeparator property on Locale is read-only:

Code Block
   /// For example, for "en_US", returns ",".
  public var groupingSeparator: String? { get }


How do I create a Locale object for testing purposes, that will simulate a custom locale the user might have configured in the System Preferences?
Hi,
it's great that you are showing localized numbers to your users!
If you are using a NumberFormatter, I'm don't think you need to test that it's behaving correctly with custom separators. This should be guaranteed by using the framework. By making a test for it, you would test the system/SDK instead of your own app.

If you’re not using a provided formatter, I'm not sure how you could test this.

If this is about making sure your test always passes without depending on the developer's locale, you can set a specific locale in the test action of your scheme, or multiple in your test plan.
Thanks for the reply. I'm not actually doing number formatting, but rather locale-sensitive numeric expression evaluation.

For example in the US:
"123,456 + 10,000 = 133,456 "
// Locale(identifier: "en_US")

In Germany:
"123.456 + 10.000 = 133.456"
// Locale(identifier: "en_DE")

Or with a custom grouping separator:
"123’456 + 10’000 = 133’456"
// How to create & test this locale programmatically?

I have tests for standard locales, but a case was reported by a customer where number recognition was failing for a custom grouping separator. The only way for me to test this at the moment is to set this custom locale in my own macOS System Preferences, which is a bit fragile. I'd like for this test to be automated, like I have for the standard locales.

There is no API to do this. Locales are essentially immutable objects, all the way down to the CFLocale level, so the only viable strategy here is to create the locale with the group separator you want. And while the locale string format supports keywords [1], there is not, alas, a keyword to override the group separator )-:

ps Can you drop me a line via email? My address is in my signature.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] See ICU > Locales and Resources > Keywords.

unicode-org.github.io/icu/userguide/locale/#keywords

For example:

Code Block
let d = Date(timeIntervalSinceReferenceDate: 637836118.0)
let df = DateFormatter()
df.dateStyle = .medium
df.locale = Locale(identifier: "ja_JP")
print(df.string(from: d))
// prints: 2021/03/19
// that is, Gregorian calendar with Japanese formatting
df.locale = Locale(identifier: "ja_JP@calendar=japanese")
print(df.string(from: d))
// prints: R3/03/19
// that is, Japanese calendar with Japanese formatting

Testing a Locale with custom grouping separator
 
 
Q