Насмешка над браузером для RSpec, без тестовой утечки - PullRequest
1 голос
/ 29 октября 2019

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

У меня есть тесты, в которых мне нужно смоделировать браузер. У меня есть фиктивный драйвер, который я настроил так:

require "watir"

def mock_driver
  browser = double("watir")
  allow(browser).to receive(:is_a?).with(Watir::Browser).and_return(true)
  allow(browser).to receive(:driver).and_return(true)
  browser
end

Единственные проблемы, с которыми я столкнулся в моем наборе тестов, - это два теста:

  context "an empiric driver is requested" do
    it "a watir browser is provided" do
      allow(Watir::Browser).to receive(:new).and_return(Empiric.browser)
      Empiric.set_browser mock_driver
    end

    it "the requested watir browser can be shut down" do
      #allow(Empiric.browser).to receive(:quit)
      Empiric.quit_browser
      #allow(mock_browser).to receive(:new).and_return(Empiric.browser)
      #Empiric.set_browser mock_driver
    end
  end

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

С этой строкой во втором тесте я получаю следующую ошибку в этом тесте:

<Double "watir"> was originally created in one example but has leaked into another
example and can no longer be used. rspec-mocks' doubles are designed to only last for
one example, and you need to create a new one in each example you wish to use it for.

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

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

    it "the requested watir browser can be shut down" do
      #allow(Empiric.browser).to receive(:quit)
      Empiric.quit_browser
      #allow(mock_browser).to receive(:new).and_return(Empiric.browser)
      Empiric.set_browser mock_driver
    end

Итак, здесь я раскомментировал последнюю строку, поэтому я устанавливаю mock_driver в этом тесте и не допускаю утечки кода.

Это, однако, возвращает точно такую ​​же ошибку в том же тесте.

Я не уверен, поможет ли это увидеть методы, которые вызываются в этом тесте, но здесь онинаходятся. Во-первых, set_browser:

def set_browser(app = :chrome, *args)
  @browser = Watir::Browser.new(app, *args)
  Empiric.browser = @browser
end

А вот quit_browser:

def quit_browser
  @browser.quit
end

Тот факт, что RSpec считал, что один тест «просачивается» в другой, заставил меня подумать, что, возможно,Мой @browser экземпляр был проблемой, в сущности состоящей в том, что сохраняется между двумя тестами. Но я не вижу, как обойти это. Я подумал, что, может быть, если я выйду из браузера в первом тесте, это поможет. Поэтому я изменил первый тест следующим образом:

it "a watir browser is provided" do
  Empiric.quit_browser
  allow(Watir::Browser).to receive(:new).and_return(Empiric.browser)
  Empiric.start_browser mock_driver
end

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

Ответы [ 2 ]

1 голос
/ 29 октября 2019

Я думаю, что вы должны использовать allow с макетом, а не Watir::Browser.

Например, что произойдет, если вы позволите браузеру-макету принимать любые вызовы браузера и получать его обратно? фиктивный браузер?

Прямо сейчас вы разрешаете «Watir :: Browser» получать эти сообщения, а это возвращает «Empiric.browser». Глядя на твой код, я понимаю, почему ты вставил это туда, но я думаю, что это может быть причиной того, что тебя здесь пугает. Я бы полностью рекомендовал не использовать mock_driver, который вы настроили. Скорее, для каждого из ваших тестов просто сделайте что-то похожее на то, что вы делаете в mock_driver. Я предполагаю, что вы включаете фиктивный драйвер как часть общего контекста, и это тоже еще одна вещь, которая очень хрупкая в RSpec. Не рекомендуется.

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

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

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

0 голосов
/ 29 октября 2019

Учитывая некоторые советы Михаэ, я хотел дать ответ с решением. Я закончил тем, что сделал это:

  context "an empiric driver is requested" do
    it "a watir browser is provided" do
      allow(Watir::Browser).to receive(:new).and_return(Empiric.browser)
      allow(Empiric.browser).to receive(:driver).and_return(true)
      expect { Empiric.start_browser :some_browser }.not_to raise_error
    end

    it "the requested watir browser can be shut down" do
      allow(Empiric.browser).to receive(:quit)
      allow(Watir::Browser).to receive(:new).and_return(Empiric.browser)
      allow(Empiric.browser).to receive(:driver).and_return(true)
      expect { Empiric.quit_browser }.not_to raise_error
    end
  end

Все это было нужно как есть, иначе я получу какую-то ошибку или другое. Я удалил свой фиктивный водитель и, по предложению Мики, просто попытался включить то, что, казалось, работало. Вышеуказанная «штуковина» - это то, что я в конечном итоге назвал сладким пятном.

Это работает в смысле освещения рассматриваемых методов. Интересно было то, что мне пришлось добавить это в мою конфигурацию RSpec:

RSpec.configure do |config|
  config.mock_with :rspec do |mocks|
    mocks.allow_message_expectations_on_nil = true
  end
end

Мне нужно было сделать это, потому что RSpec сообщал, что я звонил, что-то, что было нулевым, получало значение.

Это подняло некоторые интересные вещи, если подумать. У меня есть тест, который явно проходит. И это добавляет к моему покрытию кода. Но действительно ли тестирует действие выхода в браузере? Ну, не совсем, так как он проверял действие выхода на чем-то, что считалось нулевым.

Но - это работает. И это должно вызывать строки кода, о которых идет речь, потому что покрытие кода, как сообщал мой SimpleCov, указывает на то, что рассматриваемые операторы были проверены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...