2017-02-07 7 views
11

Я пишу тест E2E с транспортиром. Мне нужно было получить информацию из браузера и выполнить шаг несколько раз.Тесты E2E с несколькими страницами с информацией из браузера

Я тестирую один экран, который начнется, когда А

  • пользователь нажимает «Start»
  • земли на новой странице
  • Рабочий процесс ниже вызывается со счетом передается в качестве аргумента
  • id Идентификатор html не изменяется. значение изменяется при повторном запросе после отправки текущей формы.
for(i = 0 ; i < count ; i++){ 
    console.log("counter is "+i); 
    element(by('id')).evaluate('value').then(function(v) { 
    // do some action on UI based on v 
    element(by('id1')).sendKeys(v+v); 
    // submit etc., 
    // some angular code runs in the frontend. 
    } 
    // need to wait since webdriver jumps to the next one without this completing 
} 

Много сообщений блог/Документация предполагает, вы не можете использовать его в петле, но не предполагает какой-либо альтернативный способ сделать это.

Любые предложения оценены.

Никогда не используйте инструкции протрансформатора внутри цикла: Простая причина в том, что API-интерфейс webdriverJS (транспортир) является асинхронным. Операторы элементов возвращают обещание, и это обещание находится в неразрешенном состоянии, а код ниже операторов продолжает выполняться. Это приводит к непредсказуемым результатам. Следовательно, рекомендуется использовать рекурсивные функции вместо циклов.

Источник: http://engineering.wingify.com/posts/angularapp-e2e-testing-with-protractor/

Edit: обновленный вопрос с подробной информацией о процессе.

+0

вы можете поместить некоторые детали в вопросе .. как .. как это 'значение count' определяется и делает' id' изменить с каждое значение в цикле. Может быть, какой-то контекст лучше ответить на это лучше – AdityaReddy

+0

'count' передается из другой функции. Элемент 'id' изменяется во внешнем интерфейсе, но значение во время оценки не изменяется. также обновит вопрос. – Sairam

ответ

1

Looping в транспортир работает как этот

describe('Describe something', function() { 
    var testParams = [1,2,3,4,5,6,7,8,9,10]; 
    beforeEach(function() { 
     // ... 
    }); 

for (var i = 0; i < testParams.length; i++) { 
    (function (testSpec) { 
    it('should do something', function() { 
     // inside loop 
    }); 

    })(testParams[i]); 

}; 
}); 

Edit: Я мог бы быть неправильно понять ваш вопрос, но мне кажется, вы хотите, чтобы завершить все (динамический подсчет) действия на странице, прежде чем в следующий ?

it('should clear old inspections', function() { 
        inspectieModuleInspectieFixture.getRemoveInspectionButton().count().then(function (value) { 
         if(value == 0){ 
          console.log('--- no inspections to remove ---'); 
         } 
         for(var i = 0; i < value; i++){ 
          //global.waitForClickable(inspectieModuleInspectieFixture.getRemoveInspectionButtonList(i+1)); 
          inspectieModuleInspectieFixture.getRemoveInspectionButtonList(i+1).click(); 
          console.log('iteration '+i + 'count '+value) 
         }; 
        }); 
        global.wait(5000); 

      }); */ 

это рассчитывает элементы на странице, а затем выполняет действие для суммы элементов он нашел

В приведенных выше примере я использую контейнеры для хранения своих элементов, так что мой код остается читаемым (т.е. inspectieModuleInspectieFixture .getRemoveInspectionButton() имеет значение $ (". elementSelectorExample")

Прокомментирован также «global.waitForClickable», в котором я написал «модуль времени», который расширяет функциональность «wait», в в этом случае он ожидает, что элемент будет допустимым/кликабельным.

Это легко отражается, возможно что-то вроде этого:

waitForElementNoDisplay: function(element){ 
    return browser.wait(function() { 
     return element.isDisplayed().then(function(present) { 
      return !present; 
     }) 
    }); 
}, 

это сделает транспортир ПОДОЖДИТЕ недо больше не отображается элемент. (Дисплей: нет)

+1

Отличное решение. Никогда не думал об этом таким образом. Что делать, если у меня есть 2 уровня вложенности циклов 'for'. У меня есть набор страниц для прохождения и набор действий на каждой странице. Не могли бы вы указать на документацию или рекомендации для Транспортатора? – Sairam

+0

@Sairam Увы, я не думаю, что Protractor допускает петли вообще, поэтому я не могу найти какую-либо документацию о том, как ее правильно реализовать. Это фрагмент, который я снял с другого человека. Я также отказался от попыток реализовать его в реальном наборе тестов, я обнаружил, что добавленная «сложность» просто не то, что мы хотели для наших тестов, мне лучше было скопировать файл конфигурации и немного их настроить. [snip] Редактировать: Я думаю, что цикл вложенности может не быть тем, что вы хотите, вы можете захотеть что-то вроде этого (см. Редактирование сообщения) – Rheijn

+0

global.wait плохо для моего дела, так как может быть слишком много. Я искал цикл 'for' в основном и помещал' it' внутри него. – Sairam

0

Если вам необходимо выполнить некоторые действия на каждом элемент, правда, что лучше не использовать циклы. Используйте .map() или .each() или.фильтр() вместо

До сих пор не совсем уверен, что вы, что делать, но вот пример того, как я делаю подобные задачи, когда вам необходимо сделать ряд действий в зависимости от данных со страницы:

class SomePage { 

    typeValueForEachElement(elements) { 
     elements.each((elem, index)=> { 
      elem.getAttribute('value').then(value=> { 
       elem.sendKeys(value + value) 
       elem.submit() 
      }) 
     }) 

    } 
} 

new SomePage().typeValueForEachElement($$('your locator here')) 

Вот ссылка апи, которые могли бы помочь

http://www.protractortest.org/#/api?view=ElementArrayFinder.prototype.map http://www.protractortest.org/#/api?view=ElementArrayFinder.prototype.reduce http://www.protractortest.org/#/api?view=ElementArrayFinder.prototype.each http://www.protractortest.org/#/api?view=ElementArrayFinder.prototype.filter

+0

Я выполняю операции над одним и тем же элементом.но мне нужно выполнить 'n' раз на основе ввода с предыдущего экрана. – Sairam

2

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

Причина в том, что первые асинхронные вызовы выполняются после последней итерации цикла, когда i уже равен count. Таким образом, это затрудняет разрыв цикла и отслеживание значения i.

На пути к решению этой проблемы является использование рекурсивной функции:

var count = 3; 
var results = []; 

function iterate(i, n) { 
    if(i < n) { 
    console.log(`counter is ${i}`); 

    browser.refresh(); 
    return element(by.id('h-top-questions')).getText().then(function(text) { 
     results.push(`${i}:${text}`); 
     return iterate(i + 1, n); 
    }); 
    } 
} 

iterate(0, count).then(function(){ 
    console.log("done!", results); 
}); 

Но лучше всего было бы итерацию с promise.map на массив размером с числом итераций:

var count = 3; 

protractor.promise.map(Array(count).fill(0), function(v, i) { 
    console.log(`counter is ${i}`); 

    browser.refresh(); 
    return element(by.id('h-top-questions')).getText().then(function(text) { 
    return `${i}:${text}`; 
    }); 
}).then(function(results){ 
    console.log("done!", results); 
}); 

Вы также можете использовать цикл. Сначала вам нужно будет использовать оператор let, чтобы получить значение i в асинхронной функции (ES6). Затем вызовите весь синхронный код с browser.call синхронизировать выполнение:

var count = 3; 
var results = []; 

for(let i = 0 ; i < count ; i++){ 
    browser.call(function(){ 
    console.log(`counter is ${i}`); 

    browser.refresh(); 
    element(by.id('h-top-questions')).getText().then(function(text) { 
     results.push(`${i}:${text}`); 
    }); 
    }); 
} 

browser.call(function() { 
    console.log("done!", results); 
}); 
+0

На странице есть некоторые динамические данные, измененные или используемые из предыдущей итерации цикла и не могут использовать 'refresh'. Вид на странице имеет только одно текстовое поле и одно поле ввода со строкой выполнения. – Sairam

+0

@ Сайрам, обновление здесь как пример для наблюдения за порядком исполнения. Для результата предыдущей итерации вы можете получить ее в 'results [i - 1]'. –