Настройка языка схемы игнорируется в тестах модулей iOS и пользовательского интерфейса

Моя конечная цель - выпустить

xcodebuild test

из командной строки выбирая разные схемы для разных языков.

На данный момент у меня две схемы, разница между ними только в языке приложения. В одной схеме английский, в другой испанский. Если я использую Xcode для запуска приложения, оно работает хорошо, оно запускается на языке, указанном в выбранной мной схеме, и EN, и ES в порядке.

Если я запускаю тесты из Xcode, настройка языка игнорируется. Какую схему я не выберу, не важно, она всегда отображается как язык устройства. То же самое на симуляторе. То же самое при запуске тестов со схемой выбора теста xcodebuild. (Добавление эхо-команды в схему гарантирует, что будет выбран правильный вариант)

В редакторе схемы установлен флажок Использовать аргументы действия «Выполнить» и переменные окружения.

Что я делаю не так?

Спасибо.


person Androrider    schedule 17.02.2016    source источник


Ответы (1)


Да, похоже, что все переменные окружения и аргументы запуска, представленные в схемах, в тестах XCTest игнорируются.

Однако можно задать язык программно в тесте, например в методе setUp():

override func setUp() {
    super.setUp()

    // Put setup code here. This method is called before the invocation of each test method in the class.

    let app = XCUIApplication()
    app.launchArguments += ["-AppleLanguages", "(en-US)"]
    app.launchArguments += ["-AppleLocale", "\"en-US\""]

    app.launch()

}

Теперь вы можете расширить этот подход и сделать что-то вроде Snapshot:

2 вещи должны быть переданы из моментального снимка в инструмент командной строки xcodebuild:

  • Тип устройства передается через параметр назначения параметра xcodebuild.

  • Язык передается через временный файл, который записывается моментальным снимком перед запуском тестов и считывается тестами пользовательского интерфейса при запуске приложения.

В конце концов, чтобы изменить язык на основе схемы, вы можете сделать следующее:

<сильный>1. Напишите сценарий предварительного действия для теста, который создает временный файл:

mkdir -p ~/Library/Caches/xcode-helper
echo "en-US" > ~/Library/Caches/xcode-helper/language.txt

<сильный>2. Загрузите файл в setUp() и установите язык приложения:

override func setUp() {
    super.setUp()

    let app = XCUIApplication()

    let path = NSProcessInfo().environment["SIMULATOR_HOST_HOME"]! as NSString
    let filepath = path.stringByAppendingPathComponent("Library/Caches/xcode-helper/language.txt")


    let trimCharacterSet = NSCharacterSet.whitespaceAndNewlineCharacterSet()
    let language = try! NSString(contentsOfFile: filepath, encoding: NSUTF8StringEncoding).stringByTrimmingCharactersInSet(trimCharacterSet) as String

    app.launchArguments += ["-AppleLanguages", "(\(language))"]
    app.launchArguments += ["-AppleLocale", "\"\(language)\""]

    app.launch()
}

С этого момента Xcode будет запускать тест с языком/локалью, указанными в сценарии предварительного действия схемы.

ОБНОВИТЬ

Оказывается, тесты не игнорируют аргументы, представленные в схеме. Аргументы фактически передаются самому тесту, но не тестируемому приложению. Что может быть неожиданно, но имеет смысл.

При этом все, что вам нужно сделать, это:

1. Задайте -AppleLanguages (en-US) и -AppleLocale en_US аргументы запуска теста в схеме

Снимок экрана — установка ‹  code›-AppleLanguages ​​(en)‹/code› и ‹code›-AppleLocale en_US‹/code› запускают аргументы для теста в схеме

2. Передайте аргументы запуска в тесте экземпляру XCUIApplication перед вызовом метода launch().

override func setUp() {
    super.setUp()

    // Put setup code here. This method is called before the invocation of each test method in the class.

    let app = XCUIApplication()
    app.launchArguments += NSProcessInfo().arguments
    app.launch()
}
person Tom Kraina    schedule 22.04.2016
comment
Хорошо, это о тестах пользовательского интерфейса. Что насчет юнит-тестов? - person ReDetection; 09.08.2016
comment
@ReDetection IMO, вам нужно сделать что-то похожее на то, что делает Snapshot - использовать временный файл и прочитать его в тесте пользовательского интерфейса (см. первую часть ответа) - person Tom Kraina; 08.08.2017
comment
но пакет модульного тестирования не обрабатывает запуск приложения, он вообще не запускает приложение. Я не понимаю, как это должно помочь, можете ли вы уточнить? - person ReDetection; 15.08.2017
comment
Спасибо за публикацию обновления! В более новых версиях Swift просто app.launchArguments += ProcessInfo().arguments передать аргументы. - person Mark Thormann; 18.05.2018
comment
Это не работает для модульных тестов. У кого-нибудь есть обходной путь для них? - person apinho; 10.01.2019