2016-05-09 2 views
5

У меня есть четыре теста в моем наборе Capybara/Rspec, которые продолжают работать с ошибкой (настоящая проблема для развертывания CI).Что такое систематический подход к отладке периодически прерывающихся спецификаций?

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

Все они являются запросами ajax, либо отправляют удалённую форму, либо удаляются по удаленной ссылке, а затем expect(page).to have_content 'My Flash Message'.

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

e.g., 
['Country', 'State', 'City'].each do |object| 
    let(:target) { create object.to_sym } 
    it 'runs my frustrating test' do 
    end 
end 

Иногда страна терпит неудачу, иногда государство, иногда все проходит.

Я попытался добавить wait: 30 в инструкцию ожидания. Я попытался добавить sleep 30 перед оператором expect. Я все еще получаю прерывистые проходы.

Существует довольно много информации, описывающей тонкие тесты ajax, но я не нашел много о том, как отлаживать и исправлять такие проблемы.

Я очень благодарен за любые рекомендации или указатели от других, прежде чем вытащить все мои волосы!

UPDATE

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

Итак, есть ли решение?

Рекомендации по использованию инструментов отладки, такие как pry, byebug, функция отладки Poltergeist (спасибо @ Jay-Ar Polidario, @TomWalpole) были полезны для подтверждения того, что, как я думал, я уже знал, а именно, как предложено @ BM5K) что функции работают последовательно в браузере, а ошибки лежат в тестах.

Я экспериментировал с настройкой тайм-аутов и повторных попыток (@ Jay-Ar Polidario, @ BM5K), и хотя улучшение было по-прежнему непрочным решением. Что еще более важно, этот подход был похож на исправление отверстий, а не на правильное исправление, и поэтому я не был полностью доволен.

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

Пройдя этот процесс, я заметил, что все эти ошибки были связаны с «нажатием на вещи или заполнением форм», как предположил @BoraMa. Хотя в этом случае опыт был отменен - ​​мы приняли синтаксис .trigger('click'), потому что capybara + poltergeist сообщал об ошибках, нажимая на элементы с использованием click_link или find(object).click, и именно эти тесты были проблематичными.

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

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

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

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

+0

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

+0

Всегда то же самое. Я либо ожидаю флэш-контента 'Failure/Error: expect (page) .to has_content" # {target.model_name.human} был отмечен! " ожидается найти текст «Страна была отмечена!» в ...... 'или селектор' Failure/Error: expect (page) .to have_selector "a.unflag-btn" ожидается найти css "a.unflag-btn", но не было совпадений ' –

+0

' save_and_open_page 'не показывает ничего очевидного. и эти тесты проходят при запуске инсоляции и с перерывами с пакетом. –

ответ

3

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

В течение нескольких прогонов трек, тесты которого терпят неудачу. Все ли они в одной и той же контекстной группе?

Вы смешиваете и сопоставляете тесты javascript и тесты, отличные от javascript? Если это так, вы можете столкнуться с проблемами с базой данных (я видел проблемы, вызванные включением контекстного блока для сред очистки базы данных).

Убедитесь, что вы считаете любые родительским контекст блоки тестов находятся в.

И если все это не сужает поиск, использовать драгоценный камень, который позволяет вам повторить провал попытки тестов.

В прошлом году я использовал respec-retry, но в последнее время это было ненадежно. Я перешел на rspec-repeat. Я обычно оставляю их в разработке (настроен на 1 попытку) и запускается с несколькими попытками на CI (обычно 3). Таким образом, я могу получить представление о том, какие тесты являются неустойчивыми локально, но не позволяйте этим тестам разрушать мою сборку (если они не сработают последовательно).

TL; DR

Большинство прерывисто непройденных тестов я сталкиваюсь много движущихся частей (рельсы, водосвинки, очистителя базы данных, фабричной девушки, phantomjs, RSpec просто назвать несколько). Если код протестирован И часто проходят спецификации, и функция последовательно работает в браузере, возможно, какое-то взаимодействие в вашей тестовой среде является основной причиной прерывистых сбоев. Если вы не можете отследить это, повторите неудачные спецификации пару раз.

1

Если вы уверены, что на стороне сервера (Rails) и клиента (JS) нет изменяющейся переменной. Вы можете попробовать следующее, если оно будет работать. Мы использовали это для некоторой подобной проблемы, которую мы имели.

спецификации/поддержка/wait_for_ajax.rb

# ref: https://robots.thoughtbot.com/automatically-wait-for-ajax-with-capybara 
module WaitForAjax 
    def wait_for_ajax 
    Timeout.timeout(Capybara.default_max_wait_time) do 
     loop until finished_all_ajax_requests? 
    end 
    sleep(1) # ensure just because above doesn't always work 
    end 

    def finished_all_ajax_requests? 
    page.evaluate_script('jQuery.active').zero? 
    end 
end 

спецификация/особенность/YOUR_SPEC.rb

Rspec.feature 'My Feature Test', type: :feature do 
    ['Country', 'State', 'City'].each do |object| 
    let(:target) { create object.to_sym } 
    it 'runs my frustrating test' do 
     find('#my-div').click 
     wait_for_ajax 
    end 
    end 
end 

rails_helper.rb

# .. 
RSpec.configure do |config| 
    # .. 
    config.include WaitForAjax, type: :feature 
    # .. 
end 
# .. 
+3

99% времени wait_for_ajax - это всего лишь обходной путь для плохо написанных тестов, пара, связанная со сном (1), вставленным в ваш метод, и это не то, что следует рекомендовать. –

+0

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

+1

Прочтите свою ссылку, и да есть редкие случаи, но они действительно редки. Как сказано в последнем разделе этой ссылки, если вы не указываете каким-либо визуальным образом, что действие было завершено, это скорее всего плохой интерфейс, и если вы, вы должны ждать этого с Capybara, а не использовать wait_for_ajax - The одно место wait_for_ajax было действительно оправдано для запросов ajax, которые продолжались после завершения теста (и поэтому могли вызвать проблемы с БД во время очистки), и эта проблема должна была быть исправлена ​​с помощью Capybara 2.7, которая ждет их завершения автоматически. –

4

Позвольте мне рассказать историю тоже :). В последнее время мы также пытались найти и устранить проблемы с нашими периодическими ошибками при аналогичной настройке (тесты Poltergeist, JS). Тестирование оказалось более вероятным, если весь тестовый пакет был запущен по отдельности, но примерно в одной трети времени весь пакет удался. Это всего лишь пара тестов из набора, около 10, которые случайно потерпели неудачу, другие, казалось, все время работали нормально.

Сначала мы убедились, что тесты не терпят неудачу из-за проблем усечения db, оставшихся записей и т. Д. Мы сделали скриншоты на момент отказа проверить, что страница выглядела правильно.

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

Способ признать, что это действительно было проблемой для нас, было то, что мы смогли успешно удалить элемент на странице, но браузеру не удалось нажать на него.

Мы закончили с использованием не очень чистое решение - мы переписали некоторые Капибара хелперы для нажатия и взаимодействия с формами использования find и trigger внутренне:

# override capybara methods as they react badly with animations 
# (click/action is not registered then and test fails) 
# see https://github.com/teampoltergeist/poltergeist/issues/530 
def click_button(locator, *options) 
    find_button(locator, *options).trigger(:click) 
end 

def click_link(locator, *options) 
    find_link(locator, *options).trigger(:click) 
end 

def choose(locator, *options) 
    find(:radio_button, locator, *options).trigger(:click) 
end 

def check(locator, *options) 
    find(:checkbox, locator, *options).trigger(:click) 
end 

Такой подход может привести к некоторым неожиданным проблемам, потому что теперь вы сможете нажать на вещи в своих тестах, даже если они, например, перекрываются модальным div или когда они не полностью видны на странице. Но, внимательно прочитав комментарии к проблеме github, мы решили, что это путь для нас.

С тех пор у нас есть только очень редкие сбои в тестировании, которые, как представляется, связаны с другим Полтергейстом timeouts issue. Но неудачи настолько редки, что мы не чувствуем желания смотреть дальше - тесты, наконец, достаточно надежны.

+1

Вы правы. Теперь я помню, что у нас была проблема с этим также в отношении 'trigger (: click)'. Хороший материал :) –

+2

Лучшее решение - отключить анимацию в тестовом режиме, а не рисковать запуском событий на элементах, которые пользователь никогда не может щелкнуть. –

+0

Мы фактически отключили все, что могли, но теперь, когда вы это скажете, мы могли бы [сделать больше] (https://api.jquery.com/jquery.fx.off/) (я думаю, я попробую это). С другой стороны, это всегда связано с балансировкой ограниченной тестовой среды и реальным пользовательским интерфейсом, поэтому отключение анимации не гарантирует, что все работает и для пользователя. – BoraMa

Смежные вопросы