Модульное тестирование кода iPhone, использующего NSLocalizedString - PullRequest
16 голосов
/ 30 сентября 2010

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

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

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

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

Ответы [ 7 ]

10 голосов
/ 11 октября 2010

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

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

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

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

Замените YOUR_IDENTIFIER Идентификатором пакета вашего приложения (находится в файле Info.plist, ключ CFBundleIdentifier). Предполагается, что вы определили LOGIC_TESTS как макрос препроцессора only в своей цели 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 для одного из моих классов логического теста. И нет, я понятия не имею, почему я должен регистрировать все пакеты, чтобы это работало, поэтому, если у вас есть подсказка, пожалуйста, дайте мне знать!

7 голосов
/ 07 июня 2012

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

- (void)setUp
{
    [super setUp];

    NSString *bundlePath = [[NSBundle bundleForClass:[self class]] resourcePath];
    [NSBundle bundleWithPath:bundlePath];
}
4 голосов
/ 10 апреля 2012

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

#undef NSLocalizedString
#define NSLocalizedString(key, comment) [[NSBundle bundleForClass:[self class]] localizedStringForKey:(key) value:@"" table:nil]
2 голосов
/ 18 января 2016

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

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)
1 голос
/ 10 октября 2010

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

0 голосов
/ 30 марта 2018

Swift 4.1 - Xcode 9.3

Localizable.strings (en)

"TEXT_TO_LOCALIZE" = "Hello!";

Localizable.strings (es)

"TEXT_TO_LOCALIZE" = "Hola!";

XCTestCase

class AppTestCase: XCTestCase {
   func testLocalize() {
      let localizedText = "TEXT_TO_LOCALIZE".localized(for: reference)
      print(localizedText) // "Hello!" or "Hola!"
   }
}

extension String {
   public func localized(for aClass: AnyClass) -> String {
      let bundle = Bundle(for: aClass)
      return NSLocalizedString(self, tableName: nil, bundle: bundle, comment: "")
   }
}

extension XCTestCase {
   var reference: AnyClass {
      return type(of: self)
   }
} 
0 голосов
/ 01 сентября 2012

Мне кажется, что самое чистое решение - просто включить Localizable.strings в ваш пакет octest.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...