Behat Selenium - Ожидание элементов, которые скользят внутрь

У меня проблемы с Бехатом, ожидающим, пока элемент «вползет».

В меню панели администратора каждый основной элемент перемещается вниз, открывая подменю, как показано здесь:

введите здесь описание изображения

Я добавил красную линию для отображения меню и зеленую для подменю просто для ясности.

Проблема в том, что это меню «скользит». Это прекрасный эффект, но он портит мои тесты. :)

Я пытаюсь использовать функцию вращения, чтобы заставить Behat дождаться, пока подменю станет видимым, прежде чем пытаться щелкнуть в нем.

Код:

/**
 * @When I wait for :cssSelector
 * @param $cssSelector
 * @throws \Exception
 */
public function iWaitFor($cssSelector)
{
    $this->spin(function($context) use ($cssSelector) {
        /** @var $context FeatureContext */
        return !is_null($context->getSession()->getPage()->find('css', $cssSelector));
    });
}

/**
 * @When I wait for :text to appear
 * @Then I should see :text appear
 * @param $text
 * @throws \Exception
 */
public function iWaitForTextToAppear($text)
{
    $this->spin(function($context) use ($text) {
        /** @var $context FeatureContext */
        return $context->getSession()->getPage()->hasContent($text);
    });
}

/**
 * @When I wait for :text to disappear
 * @Then I should see :text disappear
 * @param $text
 * @throws \Exception
 */
public function iWaitForTextToDisappear($text)
{
    $this->spin(function($context) use ($text) {
        /** @var $context FeatureContext */
        return !$context->getSession()->getPage()->hasContent($text);
    });
}

/**
 * Based on Behat's own example
 * @see http://docs.behat.org/en/v2.5/cookbook/using_spin_functions.html#adding-a-timeout
 * @param $lambda
 * @param int $wait
 * @throws \Exception
 */
public function spin($lambda, $wait = 60)
{
    $time = time();
    $stopTime = $time + $wait;
    while (time() < $stopTime)
    {
        try {
            if ($lambda($this)) {
                return;
            }
        } catch (\Exception $e) {
            // do nothing
        }

        usleep(250000);
    }

    throw new \Exception("Spin function timed out after {$wait} seconds");
}

И фрагмент характеристики:

@javascript
Scenario Outline: Create a new piece of artwork
  Given I am logged in to the CMS as "adminUser"
  Then I should see "Artwork"
  When I follow "Artwork"
  Then I should see "Pieces" appear
  When I follow "Pieces"
  Then I should see "Manage Artwork Pieces"

Однако, хотя это прекрасно работает в моей среде разработки Vagrant, в Jenkins происходит сбой, когда он пытается follow "Pieces" после подтверждения появления «Pieces». Оба работают под управлением Selenium с Firefox в XVFB на безголовом Linux.

Это версии, которые я сейчас использую:

╔═════════════╦══════════════╦════════════╗
║ Environment ║ Development  ║ Testing    ║
╠═════════════╬══════════════╬════════════╣
║ Linux       ║ Ubuntu 14.04 ║ CentOS 6.6 ║
║ PHP         ║ 5.5.9        ║ 5.4.38     ║
║ Behat       ║ 3.0.x-dev    ║ 3.0.x-dev  ║
║ Selenium    ║ 2.45.0       ║ 2.45.0     ║
║ XVFB        ║ 1.15.1       ║ 1.15.0     ║
║ Firefox     ║ 36.0.4       ║ 31.5.0     ║
╚═════════════╩══════════════╩════════════╝

Я собираюсь убедиться, что Firefox и Selenium обновлены настолько, насколько это возможно, чтобы увидеть, решит ли это проблему, однако это было постоянной проблемой в течение некоторого времени, поэтому я не уверен.

Дополнение

Я пропустил пример фактического сообщения об ошибке:

When I follow "Carousel" # tests/Behat/Cms/Features/1.1.Carousel.feature:11
  Offset within element cannot be scrolled into view: (110, 17): http://www.###.co.uk/admin/fp/carousel
  Build info: version: '2.44.0', revision: '76d78cf', time: '2014-10-23 20:02:37'

Это сразу после Then I should see "Carousel" appear

Кроме того, ошибки возникают почти случайно. Мне нужен надежный способ убедиться, что тест не будет продолжаться до тех пор, пока страница не будет в состоянии, позволяющем продолжить его. Я хочу избежать чего-либо вроде «ожидания» или всего, что зависит от JavaScript или Selenium в частности (на случай, если я переключусь на другой драйвер).

Обновление: Обновлен Selenium на тестовом компьютере до версии 2.45.0, проблема осталась. Исправленная версия PHP в Dev Environment выше, была 5.4, на самом деле 5.5.9.


person DanielM    schedule 13.04.2015    source источник


Ответы (1)


Я считаю, что исправил это, но я не уверен на 100% в причине, поэтому, пожалуйста, поправьте меня, если я ошибаюсь.

Я предполагаю, что проверка содержимого страницы всегда будет возвращать значение true, независимо от того, видна она или нет. Вместо этого я переключился на использование утверждений, предоставляемых Mink, которые реализуются независимо для каждого драйвера. В этом случае мы просим Selenium подумать о том, присутствует ли элемент или нет.

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

Вот новый код.

/**
 * @When I wait for :text to appear
 * @Then I should see :text appear
 * @param $text
 * @throws \Exception
 */
public function iWaitForTextToAppear($text)
{
    $this->spin(function(FeatureContext $context) use ($text) {
        try {
            $context->assertPageContainsText($text);
            return true;
        }
        catch(ResponseTextException $e) {
            // NOOP
        }
        return false;
    });
}

/**
 * @When I wait for :text to disappear
 * @Then I should see :text disappear
 * @param $text
 * @throws \Exception
 */
public function iWaitForTextToDisappear($text)
{
    $this->spin(function(FeatureContext $context) use ($text) {
        try {
            $context->assertPageContainsText($text);
        }
        catch(ResponseTextException $e) {
            return true;
        }
        return false;
    });
}

С тех пор я дважды запускал наборы тестов, причем варианты этой проверки повторялись примерно по 100 раз в каждом, и они оба вернулись в порядке. Я пока оставлю вопрос открытым на случай, если кто-то захочет дать лучший ответ/объяснение.

person DanielM    schedule 14.04.2015
comment
Помечено как правильное, поскольку у меня больше не было проблем с этим, и никто другой не нашел ответа. :) - person DanielM; 06.05.2015
comment
Отсутствует метод spin() - person FDisk; 26.05.2016
comment
Это в вопросе. - person DanielM; 26.05.2016