Dev (Back & Front)ARTIGO

Vida longa ao PhantomJS, vamos usar o Chrome Headless

No seguinte artigo, o autor apresenta as vantagens do PhantomJS e fala sobre como o Chrome Headless pode ser uma boa solução.

Se você fizer Feature Specs, o ato de carregar um servidor de aplicativos real e, em seguida, um navegador headless real para fazer testes reais de recursos do usuário, então você conhece Capybara e um dos seus drivers mais conhecidos, o Poltergeist. Poltergeist envolve/acaba com o PhantomJS, que é um conhecido navegador headless baseado em WebKit.

Mas o WebKit é conhecido por ser muito complicado de lidar. Então, eu só posso imaginar o pesadelo para manter o PhantomJS, que é semelhante a um navegador web completo como o Chrome ou o Safari.

Portanto, não é de se admirar que, quando a equipe do Chrome anunciou a disponibilidade do Chrome Driver, o mantenedor do PhantomJS decidiu renunciar.

Se você conhece os colaboradores do PhantomJS, agradeça, pois ajudaram a criar recursos de usuário mais sólidos.

Dito isto, não tenha medo. Você pode substituir facilmente Poltergeist/PhantomJS por Selenium WebDriver/Chrome Driver na sua configuração do RSpec/Capybara.

Meu amigo Lucas Caton escreveu sobre isso em junho deste ano. Siga o blog dele também.

Se você estiver usando o Linux com o navegador Chromium, não precisa instalar nada, pois o Chrome Driver vem com o Chromium. Caso contrário, você precisa instalar os pacotes adequados para o seu sistema operacional. Por exemplo, brew install chromedriver para OS X ou pacaur -S chromedriver no Arch se você não gosta de ter Chromium ao redor. Talvez você precise ajustar seu PATH no Ubuntu.

Regra geral: instale o Chromium.

No meu caso, isso é o que tive que mudar:

# Gemfile
- gem "poltergeist"
+ gem "selenium-webdriver"
+ gem "rspec-retry"

Então, na configuração do Capybara:

Capybara.server = :puma # Until your setup is working
Capybara.server = :puma, { Silent: true } # To clean up your test output

- Capybara.register_driver :poltergeist do |app|
-   options = {
-     timeout: 3.minutes,
-     phantomjs_options: [
-       '--proxy-type=none',
-       '--load-images=no',
-       '--ignore-ssl-errors=yes',
-       '--ssl-protocol=any',
-       '--web-security=false'
-     ]
-   }
-   Capybara::Poltergeist::Driver.new(app, options)
- end
- Capybara.javascript_driver = :poltergeist

+ Capybara.register_driver :chrome do |app|
+   capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
+     chromeOptions: {
+       args: %w[ no-sandbox headless disable-popup-blocking disable-gpu window-size=1280,1024]
+     }
+   )
+ 
+   Capybara::Selenium::Driver.new(app, browser: :chrome, desired_capabilities: capabilities)
+ end
+ 
+ Capybara::Screenshot.register_driver :chrome do |driver, path|
+   driver.save_screenshot(path)
+ end
+ 
+ Capybara.javascript_driver = :chrome

Capybara.default_max_wait_time = 5 # you may want to increase this timeout if your app is heavy to load

Nas especificações de recursos, às vezes o próprio Rails leva muito tempo para carregar, compilar ativos/recursos, etc. E as primeiras especificações dos recursos podem demorar. Para evitar uma falha na execução do teste, recomenda-se adicionar a gema rspec-retry, como fiz acima, e adicionar o seguinte ao seu spec/rails_helper.rb:

require 'rspec/retry'

RSpec.configure do |config|
  ...
  # show retry status in spec process
  config.verbose_retry = true
  # Try twice (retry once)
  config.default_retry_count = 2
  # Only retry when Selenium raises Net::ReadTimeout
  config.exceptions_to_retry = [Net::ReadTimeout]
  ...
end

E isso deveria ser assim. Eu não tive que tocar em nenhuma das minhas especificações de recurso e todas executaram lindamente. Então, parabéns para as respectivas equipes que mantêm Capybara, Selenium-WebDriver por suportar isso.

Se você é um desenvolvedor Node.js, provavelmente usou algo como o Casper, que também diz apoiar o Chrome Headless. Mas enquanto estivermos nisso, você também deveria conferir o Puppeteer, da própria equipe do Google. É uma biblioteca baseada em garantia/promessa onde você pode codificar assim:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({path: 'example.png'});

  await browser.close();
})();

Então, sim, o Chrome Headless parece ser uma opção muito boa, pois a maioria dos usuários realmente usa o navegador Chrome, por isso significa que devemos ter especificações de recursos e também ferramentas de rastreamento web mais confiáveis.

***

Artigo traduzido com autorização do autor. Publicado originalmente em: http://www.akitaonrails.com/2017/10/31/beginner-long-live-phantomjs-let-s-use-chrome-headless-now

Fábio AkitaAutor

Co-fundador da Codeminer 42, empresa de desenvolvimento de software principalmente para startups. Desde 2008 é o criador e organizador do Rubyconf Brasil, uma das maiores conferências de tecnologia da América Latina. Tem experiência de 20 anos no mercado de software, tendo passado pelo mercado de grandes agências, consultoria SAP corporativo e pelo primeiro boom de startups em 2000.

Ver perfil