Транспортир не проходит мои тесты без метода done()

Я на самом деле заканчиваю модульные тесты моего приложения Angular. В настоящее время я работаю над тестами E2E, используя Protractor и Jasmine. К сожалению, у меня есть следующая проблема:

Я провел множество исследований в Интернете, таких как http://ramonvictor.github.io/protractor/slides/ и я явно никогда не видел использование "готового" обратного вызова для запуска тестов.

Этот первый тест выполняется на странице createUser и удостоверяется, что атрибут вкладки пользователя установлен в активное состояние. Он проходит ТОЛЬКО если я использую готовый метод, который я не должен использовать.

'use strict';

var UserCreate = require('./page-objects/userCreate.pageObjects');

describe('on init', function () {

    beforeEach(function() {
       var rootUrl = browser.baseUrl + '/#/users/create';
       browser.driver.get(rootUrl);
    });

    it('should set the user tab active', function(done) { // DONE callback
        UserCreate.tabs.getAttribute('class').then(function(value) {
            expect(value).toEqual('active');
            done(); // calling callback
        });
     });
 });

Если я повторяю тот же тест без использования done(), тест проходит, даже если на этот раз я хочу, чтобы он не прошел.

'use strict';

var UserCreate = require('./page-objects/userCreate.pageObjects');

describe('on init', function () {

    beforeEach(function() {
       var rootUrl = browser.baseUrl + '/#/users/create';
       browser.driver.get(rootUrl);
    });

    it('should set the user tab active', function() {
        UserCreate.tabs.getAttribute('class').then(function(value) {
            expect(value).toEqual('activeWRONG');
        });
     });
 });

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

Вот мой конфигурационный файл:

 /* conf.js */
'    use strict';

exports.config = {
rootElement: '#myApp',
directConnect: true,
seleniumAddress: 'http://localhost:4444/wd/hub',
capabilities: {
    browserName: 'chrome',
    shardTestFiles: true,
    maxInstances: 1
},
framework: 'jasmine',
// specs: ['./*.spec.js'],
baseUrl: 'http://localhost:9001',
defaultTimeoutInterval: 0000,
jasmineNodeOpts: {
    showColors: true,
},
suites: {
    wip:        './userCreate.spec.js',
    all:        './*spec.js'
},
onPrepare: function() {
    browser.driver.get('http://localhost:9001/#/');
    element(by.id('ld-link-login')).click();
    browser.sleep(500);

    element(by.model('username')).sendKeys('test');
    element(by.model('password')).sendKeys('test');
    element(by.id('nv-login-submit')).click();

    return browser.driver.wait(function() {
        return browser.driver.getCurrentUrl().then(function(url) {
            return /dashboard/.test(url);
        });
    }, 10000);
}
};

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

Спасибо за помощь.

Редактировать:

Версия транспортира:./node_modules/.bin/protractor - версия дает версию 3.2.2

userCreate.pageObjects:

'use strict';

 module.exports = {
    tabs: element(by.id('cc-tab-user'))
  };

5 ответов

Это может происходить, если ваш тест создает параллельный TaskQueue в потоке управления вашего теста. Что такое done() для чего и как его использовать (транспортир, жасмин) Я написал несколько примеров тестов, дающих противоречивые результаты из-за этого.

Чтобы выяснить, является ли это вашей проблемой, вы можете распечатать поток управления в различных точках теста:

console.log(protractor.promise.controlFlow().getSchedule(false));

Это из-за потока управления, который не работает должным образом в вашем коде. Поток управления основан на концепции задач и очередей задач. Задачи - это функции, которые определяют базовую единицу работы для выполняемого потока управления. Каждая задача запланирована через ControlFlow#execute(), которая будет возвращать ManagedPromise, который будет решен с результатом задачи.

Следующее должно работать.

let UserCreate = require('./pageobject.page.js');
describe('should navigate to url', function () {
    beforeEach(function() {
      url = `${browser.baseUrl}/#/users/create`;
      browser.driver.get(url);
    });
    it('should set the user tab active', function() {
   expect(UserCreate.tabs.getAttribute('class')).toEqual('activeWRONG');
    });
});

У вас проблема с тем, как вы определяете объект Page, ведущий к проблеме с порядком разрешения обещаний. Следуйте руководству по стилю и измените его на:

var UserCreatePage = function() {
  this.tabs = element(by.id('cc-tab-user'));
};

module.exports = UserCreatePage;

Использование:

'use strict';

var UserCreatePage = require('./page-objects/userCreate.pageObjects');

describe('on init', function () {
    var userCreatePage;

    beforeEach(function() {
       var rootUrl = browser.baseUrl + '/#/users/create';
       browser.driver.get(rootUrl);

       userCreatePage = new UserCreatePage();
    });

    it('should set the user tab active', function() {
        userCreatePage.tabs.getAttribute('class').then(function(value) {
            expect(value).toEqual('activeWRONG');
        });
     });
 });

Это ожидаемое поведение. Если вы не попросите done() Функция Жасмин будет считать ваш тест синхронным и завершенным, не дожидаясь выполнения обещания. Когда вы просите об этом, ваш тест стал асинхронным и потерпит неудачу, если done() не вызывался до истечения времени ожидания (по умолчанию 5 секунд). Для получения дополнительной информации см. http://jasmine.github.io/2.0/introduction.html.

Ваша проблема в том, что вы используете then() пройти value к вашему expect-заявление.then() создает новую асинхронную задачу, которая отбрасывается как подзадача. В результате этого ваш it сначала заканчивается result = success, а затем выполняется ваше ожидание. Это задокументировано в документации Promise/ControlFlow Selenium.

Как expect() уже разворачивает / выполняет обещание, нет необходимости then() в твоем случае.

С вашим done это работает, потому что вы берете на себя управление выполнением и предотвращаете it продолжить / закончить до вашего then() закончен.

Попробуй это:

'use strict';

var UserCreate = require('./page-objects/userCreate.pageObjects');

describe('on init', function () {

    beforeEach(function() {
       var rootUrl = browser.baseUrl + '/#/users/create';
       browser.driver.get(rootUrl);
    });

    it('should set the user tab active', function() {
        expect(UserCreate.tabs.getAttribute('class')).toEqual('activeWRONG');
    });
});
Другие вопросы по тегам