на хосте, на котором запущен экземпляр Instruments, выполняющий тесты.

аюсь использовать UIAutomation от Apple для написания модульных тестов для приложения iOS, имеющего компонент на стороне сервера. Чтобы настроить тестовый сервер в различных состояниях (а также смоделировать двух клиентов, общающихся через мой сервер), я хотел бы выдавать HTTP-запросы на получение из моего теста на основе JavaScript.

Может ли кто-нибудь привести пример того, как выдавать HTTP-запросы GET непосредственно из тестов JavaScript UIAutomation или как вызывать сценарий оболочки из моих тестов JavaScript UIAutomation?

Кстати, большинство основных объектов, доступных всем браузерам, отсутствуют во время выполнения UIAutomation. Попробуйте, например, использовать XMLHTTPRequest, и вы получите сообщение об исключении, которое не может найти переменную.

Спасибо!

Ответы на вопрос(1)

Мне удалось обойти это, отправив HTTP-запросы клиенту iOS для обработки и возврата результатов в UIAlertView. Обратите внимание, что все модификации кода iOS заключены в директивы условной компиляции DEBUG #if.

Сначала настройте клиент для отправки уведомлений в случае сотрясения устройства.Прочтите этот пост для получения дополнительной информации.

Далее, в свой делегат основного приложения iOS добавьте этот код:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(deviceShakenShowDebug:)
                                             name:@"DeviceShaken" 
                                           object:nil];

Затем добавьте метод, который выглядит примерно так:

- (void) deviceShakenShowDebug:(id)sender
{
    if (!self.textFieldEnterDebugArgs)
    {
        self.textFieldEnterDebugArgs = [[[UITextField alloc] initWithFrame:CGRectMake(0, 0, 260.0, 25.0)] autorelease];
        self.textFieldEnterDebugArgs.accessibilityLabel = @"AlertDebugArgsField";
        self.textFieldEnterDebugArgs.isAccessibilityElement = YES;
        [self.textFieldEnterDebugArgs setBackgroundColor:[UIColor whiteColor]];
        [self.tabBarController.selectedViewController.view addSubview:self.textFieldEnterDebugArgs];
        [self.tabBarController.selectedViewController.view bringSubviewToFront:self.textFieldEnterDebugArgs];
    }
    else
    {
        if ([self.textFieldEnterDebugArgs.text length] > 0)
        {
            if ([self.textFieldEnterDebugArgs.text hasPrefix:@"http://"])
            {
                [self doDebugHttpRequest:self.textFieldEnterDebugArgs.text];    
            }
        }
    }
}

- (void)requestDidFinishLoad:(TTURLRequest*)request
{
        NSString *response = [[[NSString alloc] initWithData:((TTURLDataResponse*)request.response).data 
                                                    encoding:NSUTF8StringEncoding] autorelease];

        UIAlertView *resultAlert = 
            [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Request Loaded",@"")
                                       message:response
                                      delegate:nil
                             cancelButtonTitle:NSLocalizedString(@"OK",@"")
                             otherButtonTitles:nil] autorelease];
        resultAlert.accessibilityLabel = @"AlertDebugResult";
        [resultAlert show];
}

Этот код добавит UITextField к самому контроллеру вида сверху после встряхивания, хлопнувшего прямо над любой панелью навигации или другим элементом пользовательского интерфейса. UIAutomation или вы, пользователь, можете вручную ввести URL-адрес в этот UITextField. Когда вы снова встряхиваете устройство, если текст начинается с «http», оно выдаст HTTP-запрос в коде (упражнение для читателя, чтобы реализовать doDebugHttpRequest).

Затем в моем файле JavaScript UIAutomation я определил следующие две функции:

function httpGet(url, delayInSec) {
  if (!delayInSec) delay = 1;
  var alertDebugResultSeen = false;
  var httpResponseValue = null;

  UIATarget.onAlert = function onAlert(alert) {    
    httpResponseValue = alert.staticTexts().toArray()[1].name();
    alert.buttons()[0].tap();
    alertDebugResultSeen = true;
  }

  var target = UIATarget.localTarget();
  var application = target.frontMostApp();
  target.shake(); // bring up the input field
  application.mainWindow().textFields()["AlertDebugArgsField"].setValue(url);
  target.shake(); // send back to be processed
  target.delay(delayInSec);
  assertTrue(alertDebugResultSeen);
  return httpResponseValue;
}

function httpGetJSON(url, delayInSec) {
  var response = httpGet(url, delayInSec);
  return eval('(' + response + ')');
}

Теперь, в моем файле JavaScript, я могу позвонить

httpGet('http://localhost:3000/do_something')

и он выполнит HTTP-запрос. Если я хочу вернуть данные JSON с сервера, я звоню

var jsonResponse = httpGetJSON('http://localhost:3000/do_something')

Если я знаю, что это будет длительный звонок, я звоню

var jsonResponse = httpGetJSON('http://localhost:3000/do_something', 10 /* timeout */)

Я успешно использую этот подход уже несколько недель.

 esilver30 июл. 2011 г., 00:53
Если вы найдете один, я все уши. Есть такжеcorner.squareup.com/2011/07/ios-integration-testing.html но он использует недокументированные API, очевидно. Жаль, что решение Apple отстой так сильно.
 Maciek Sawicki29 июл. 2011 г., 15:34
выглядит довольно уродливый взломать. Но это должно работать :). Но я ищу инструмент, который позволяет делать это без изменения кода iOS ...

Ваш ответ на вопрос