Модуль тестирования iPhone-кода, который использует NSLocalizedString

У меня есть приложение iOS4.1 для iPhone, которое использует локализованные строки. Я только что начал строить модульные тесты, используя SenTestingKit. Я смог успешно протестировать множество разных типов значений.

Я не могу правильно протестировать какой-либо из моего кода, который использует вызовы NSLocalizedString, потому что, когда код работает в моей цели LogicTests, все вызовы в NSLocalizedString возвращают только строковый ключ.

Я добавил файл Localizable.strings в цель LogicTests.

Мой вопрос: как мне настроить мою цель LogicTests, чтобы вызовы NSLocalizedString вернули локализованную строку, а не строковый ключ.

Ответы

Ответ 1

Эта проблема сводила меня с ума, но я смог заставить NSLocalizedString вести себя.

zoul был прав, если вы напечатаете mainBundle на консоли в логическом тесте, это не тот же пакет, который содержит файл Localizable.strings. Вам нужно условно переопределить NSLocalizedString всякий раз, когда вы запускаете модульные тесты. Я сделал это в следующих шагах:

  • Нам нужен способ рассказать, когда мы находимся в целевом задании логических тестов, поэтому добавьте что-то вроде LOGIC_TESTS в целевую настройку сборки Preprocessor Macros для логических тестов.
  • В моем коде есть только 1 место, где мне нужно переопределить NSLocalizedString, поэтому я смог поместить следующий код в заголовок, соответствующий этому классу. Если у вас возникла эта проблема в нескольких местах, я бы предложил поместить следующий код в заголовок и #include -в его, где он вам нужен (я попытался использовать файл .pch, но он не работает в Logic Tests). В любом случае, поместите это где-нибудь в заголовок класса (ов), которые используют NSLocalizedString:

    #ifdef LOGIC_TESTS
    #undef NSLocalizedString
    #define NSLocalizedString(key, comment) [[NSBundle bundleWithIdentifier:@"YOUR_IDENTIFIER"] localizedStringForKey:(key) value:@"" table:nil]
    #endif
    

Замените YOUR_IDENTIFIER идентификатором Bundle вашего приложения (найденным в вашем файле Info.plist, ключ CFBundleIdentifier). Предполагается, что вы определили LOGIC_TESTS как макрос препроцессора только в своей целевой логике.

edit: Любопытно, что после удаления кода отладки это решение перестало работать. Похоже, вам нужно обмануть Xcode и загрузить пакет. Следующее делает следующее:

NSString *path = @"path_to_main_bundle";
NSBundle *bundle = [NSBundle bundleWithPath:path];
NSLog(@"bundles: %@", [NSBundle allBundles]);

Где path_to_main_bundle находится == [[NSBundle mainBundle] bundlePath] при запуске основной цели. Просто зарегистрируйте его один раз в gdb или с помощью NSLog в своем делете приложения, чтобы захватить путь. Он должен выглядеть примерно так: /Users/YOUR_USER_NAME/Library/Application Support/iPhone Simulator/4.1/Applications/UUID_LOTS_OF_LETTERS_AND_NUMBERS_HERE/App.app.

Я поместил этот код в вызов setUp для одного из моих логических тестовых классов. И нет, я понятия не имею, почему мне приходится регистрировать allBundles, чтобы он работал, поэтому любой, у кого есть ключ, сообщите мне!

Ответ 2

Я смог использовать NSLocalizedString, используя следующий код в настройке для моего unit test

- (void)setUp
{
    [super setUp];

    NSString *bundlePath = [[NSBundle bundleForClass:[self class]] resourcePath];
    [NSBundle bundleWithPath:bundlePath];
}

Ответ 3

Я сталкиваюсь с той же проблемой, и, благодаря @kevboth, я решаю это, добавив две строки в YourUnitTests-Prefix.pch:

#undef NSLocalizedString
#define NSLocalizedString(key, comment) [[NSBundle bundleForClass:[self class]] localizedStringForKey:(key) value:@"" table:nil]

Ответ 4

Может быть, NSLocalizedString будет работать только внутри тестов приложения? Это макрос, который вызывает localizedStringForKey:value:table: в основном пакете. Может быть, +[NSBundle mainBundle] возвращает что-то в целевом тестировании?

Ответ 5

Ярлык для Swift: Это простая версия, которая может быть распространена на различные варианты использования (например, с использованием табличных имен).

public func NSLocalizedString(key: String, referenceClass:AnyClass) -> String 
{
    let bundle = NSBundle(forClass: referenceClass)
    return NSLocalizedString(key, tableName:nil, bundle: bundle, comment: "")
}

Этот глобальный метод может быть помещен в один файл .swift или где-то еще вне области видимости класса. Используйте его так:

NSLocalizedString("YOUR-KEY", referenceClass: self)

Ответ 6

Самое чистое решение кажется мне просто включать Localizable.strings в ваш самый острый пакет.