Запущенные тесты PHPUnit в определенном порядке

Элемент, который вы пытались найти, не был в DOM , когда ваш скрипт работал.

Позиция вашего DOM-зависимого скрипта может оказать глубокое влияние на его поведение. Браузеры анализируют HTML-документы сверху донизу. Элементы добавляются в DOM, и сценарии выполняются (как правило), когда они встречаются. Это означает, что порядок имеет значение. Как правило, скрипты не могут найти элементы, которые появляются позже в разметке, потому что эти элементы еще не добавлены в DOM.

Рассмотрим следующую разметку; сценарий # 1 не находит

, а сценарий # 2 преуспевает:


test div

Итак, что вы должны делать? У вас есть несколько вариантов:


Вариант 1: Переместите свой скрипт

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


  
  

Примечание: размещение скриптов внизу как правило, считается лучшей практикой .


Вариант 2: jQuery's ready()

Отмените свой сценарий до тех пор, пока DOM не будет полностью проанализирован, используя ready() :



Примечание. Вы можете просто привязать к DOMContentLoaded или window.onload, но у каждого есть свои оговорки. jQuery ready() предоставляет гибридное решение.


Вариант 3: Делегирование событий

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

blockquote>

Когда элемент вызывает событие (при условии, что это bubbling g6], и ничто не останавливает его распространение), каждый родитель в родословной этого элемента также получает событие. Это позволяет нам привязать обработчик к существующему элементу и примерным событиям, когда они пузырятся от его потомков ... даже те, которые добавлены после присоединения обработчика. Все, что нам нужно сделать, это проверить событие, чтобы узнать, был ли он поднят нужным элементом и, если да, запустите наш код.

jQuery on() выполняет эту логику для нас. Мы просто предоставляем имя события, селектор для желаемого потомка и обработчик событий:



Примечание: Обычно этот шаблон зарезервированы для элементов, которые не существовали во время загрузки или , чтобы избежать прикрепления большого количества обработчиков. Также стоит отметить, что, пока я прикреплял обработчик к document (для демонстрационных целей), вы должны выбрать ближайшего надежного предка.


Вариант 4: Атрибут defer

Используйте атрибут defer в

Для справки, вот код из этого внешнего скрипта :

document.getElementById("test").addEventListener("click", function(e){
   console.log("clicked: %o", this); 
});

Примечание: атрибут defer, безусловно, кажется , как волшебная пуля , но важно знать об оговорках ... 1. defer может использоваться только для внешних скриптов, т. е. для тех, у кого есть атрибут src. 2. знать о поддержке браузера , то есть: ошибка реализации в IE & lt; 10

57
задан reformed 28 January 2017 в 06:18
поделиться

6 ответов

Возможно, в Ваших тестах существует проблема проектирования.

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

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

можно ли быть более конкретны относительно того, почему Вам нужен тот же объект для тестов N?

48
ответ дан Fabio Gomes 24 November 2019 в 19:11
поделиться

Если Вы хотите, чтобы Ваши тесты совместно использовали различные объекты помощника и настройки, можно использовать setUp(), tearDown() для добавления к sharedFixture свойство.

8
ответ дан Gary Richardson 24 November 2019 в 19:11
поделиться

Действительно существует проблема с Вашими тестами, если они должны работать в определенном порядке. Каждый тест должен быть полностью независим от других: это помогает Вам с дефектной локализацией и позволяет Вам становиться повторяемыми (и поэтому debuggable) результаты.

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

1
ответ дан Tim Post 24 November 2019 в 19:11
поделиться

PHPUnit поддерживает тестовые зависимости через аннотацию @depends .

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

class StackTest extends PHPUnit_Framework_TestCase
{
    public function testEmpty()
    {
        $stack = array();
        $this->assertEmpty($stack);

        return $stack;
    }

    /**
     * @depends testEmpty
     */
    public function testPush(array $stack)
    {
        array_push($stack, 'foo');
        $this->assertEquals('foo', $stack[count($stack)-1]);
        $this->assertNotEmpty($stack);

        return $stack;
    }

    /**
     * @depends testPush
     */
    public function testPop(array $stack)
    {
        $this->assertEquals('foo', array_pop($stack));
        $this->assertEmpty($stack);
    }
}

Однако важно отметить, что тесты с неразрешенными зависимостями не будут выполняться , а не (желательно, поскольку это быстро привлекает внимание к провалу теста). Поэтому при использовании зависимостей важно уделять особое внимание.

137
ответ дан 24 November 2019 в 19:11
поделиться

PHPUnit позволяет использовать аннотацию '@depends', которая задает зависимые случаи тестирования и позволяет передавать аргументы между зависимыми случаями тестирования.

7
ответ дан 24 November 2019 в 19:11
поделиться

На мой взгляд, возьмем следующий сценарий, в котором мне нужно протестировать создание и уничтожение определенного ресурса.

Изначально у меня было два метода: а. testCreateResource и b. testDestroyResource

a. testCreateResource

<?php
$app->createResource('resource');
$this->assertTrue($app->hasResource('resource'));
?>

b. testDestroyResource

<?php
$app->destroyResource('resource');
$this->assertFalse($app->hasResource('resource'));
?>

Я думаю, что это плохая идея, поскольку testDestroyResource зависит от testCreateResource. И лучше было бы сделать

а. testCreateResource

<?php
$app->createResource('resource');
$this->assertTrue($app->hasResource('resource'));
$app->deleteResource('resource');
?>

b. testDestroyResource

<?php
$app->createResource('resource');
$app->destroyResource('resource');
$this->assertFalse($app->hasResource('resource'));
?>
2
ответ дан 24 November 2019 в 19:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: