├── .gitignore ├── AcessandoBancoDeDados └── acessa-bd-mysql.md ├── CronsForadoControle └── um-wait-diferente.md ├── DebugComPry ├── cucumber │ ├── Gemfile │ ├── Gemfile.lock │ ├── cucumber.yml │ └── features │ │ ├── specs │ │ └── simple-example-to-test.feature │ │ ├── step_definitions │ │ └── simple-example.rb │ │ └── support │ │ ├── config │ │ ├── hooks.rb │ │ ├── prod-env.yaml │ │ ├── qa-env.yaml │ │ └── staging-env.yaml │ │ └── env.rb └── debug-seus-testes.md ├── Elementos ├── id-dinamico-classes-iguais.md └── modais.md ├── LICENSE ├── MinhaEstrutura ├── cucumber │ └── features │ │ └── support │ │ └── env.rb └── estrutura-do-projeto.md ├── Navegadores&Drivers ├── chromedriver-options.md ├── chromedriver.md └── geckodriver.md ├── PageObjects ├── page-objects-siteprism │ └── page-objects-siteprism.md ├── page-step-objects │ └── page-step-objects.md └── visao-geral │ └── visao-geral.md ├── PreparandoParaEscalar ├── cucumber │ ├── Gemfile │ ├── cucumber.yml │ └── features │ │ └── support │ │ ├── config │ │ ├── hooks.rb │ │ ├── prod-env.yaml │ │ ├── qa-env.yaml │ │ └── staging-env.yaml │ │ └── env.rb └── preparando-para-escalar.md ├── README.md ├── TrabalhandoComPlanilhas ├── README_usando_planilhas.md └── features │ ├── Gemfile │ ├── Gemfile.lock │ ├── specs │ └── planilhas.feature │ ├── steps │ ├── xlsx-example-steps.rb │ └── xlsx_example.xlsx │ └── support │ └── env.rb └── UploadArquivos └── upload.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | /.config 4 | /coverage/ 5 | /InstalledFiles 6 | /pkg/ 7 | /spec/reports/ 8 | /spec/examples.txt 9 | /test/tmp/ 10 | /test/version_tmp/ 11 | /tmp/ 12 | 13 | # Used by dotenv library to load environment variables. 14 | # .env 15 | *.DS_Store 16 | 17 | ## Specific to RubyMotion: 18 | .dat* 19 | .repl_history 20 | build/ 21 | *.bridgesupport 22 | build-iPhoneOS/ 23 | build-iPhoneSimulator/ 24 | 25 | ## Specific to RubyMotion (use of CocoaPods): 26 | # 27 | # We recommend against adding the Pods directory to your .gitignore. However 28 | # you should judge for yourself, the pros and cons are mentioned at: 29 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 30 | # 31 | # vendor/Pods/ 32 | 33 | ## Documentation cache and generated files: 34 | /.yardoc/ 35 | /_yardoc/ 36 | /doc/ 37 | /rdoc/ 38 | 39 | ## Environment normalization: 40 | /.bundle/ 41 | /vendor/bundle 42 | /lib/bundler/man/ 43 | 44 | # for a library or gem, you might want to ignore these files since the code is 45 | # intended to run in multiple environments; otherwise, check them in: 46 | # Gemfile.lock 47 | # .ruby-version 48 | # .ruby-gemset 49 | 50 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 51 | .rvmrc 52 | -------------------------------------------------------------------------------- /AcessandoBancoDeDados/acessa-bd-mysql.md: -------------------------------------------------------------------------------- 1 | # Acessando o banco de dados para fins de teste. 2 | 3 | Fala pessoal, de uns tempos para cá algumas pessoas me abordam com a seguinte dúvida: "É possível persistir os dados no banco de dados?" e a resposta é sim, é possível realizar qualque ação no BD, desde consulta até deleção. Bem, eu vou falar um pouco de uma gem chamada [mysql2](https://github.com/brianmario/mysql2) que executa bem esse papel. 4 | 5 | Mas não é assim tão fácil de configurar um ambiente para essa gem, ou seja, não adianta sair dando "gem install mysql2" que não vai funcionar. Para que a instalção faça sentido, vamos precisar dos pré requisitos: 6 | 7 | ```ruby 8 | Instalar: 9 | - PostgresSQL = sudo apt-get install postgresql 10 | - Phyton = sudo apt-get install python-psycopg2 11 | - Libs = sudo apt-get install libpq-dev 12 | ``` 13 | E vamos precisar das seguintes gems instaladas: 14 | 15 | ```ruby 16 | Obs.: Sabe que o ideal é colocar no Gemfile certo?? 17 | 18 | gem install pg 19 | gem install mysql2 20 | gem install sqlite3 21 | ``` 22 | Então se você tem uma aplicação cujo o banco de dados seja MySql então essa gem vai servir pra ti. Caso tenha outros BDs, aguarde o complemento desse, que vai falar de outra gem, mas por hora concentre nesse =). 23 | 24 | Eu acho interessante a vontade de persistir os dados no banco de dados, mas indo um pouco além, quando passamos a pensar em testes na camada de BI (em breve farei um repositório sobre isso) faz muito mais sentido. 25 | 26 | Bem, então como vai ficar nosso Gemfile: 27 | 28 | ```ruby 29 | source "https://rubygems.org" 30 | 31 | gem 'capybara' 32 | gem 'cucumber' 33 | gem 'selenium-webdriver' 34 | gem 'pg' 35 | gem 'sqlite3' 36 | gem 'mysql2' 37 | gem 'rspec' 38 | ``` 39 | 40 | E nosso env: 41 | 42 | ```ruby 43 | require 'capybara/cucumber' 44 | require 'selenium-webdriver' 45 | require 'pg' 46 | require 'sqlite3' 47 | require 'mysql2' 48 | require 'rspec' 49 | ``` 50 | 51 | # Usando o Mysql2 52 | 53 | Vamos imaginar que ja temos um step e queremos fazer uma consulta no banco para sei lá, validar se o nome que colocamos no teste está registrado de forma correta. Com esse cenário, vamos trabalhar da seguinte maneira: 54 | 55 | ```ruby 56 | Entao(/^o nome cadastrado devera estar salvo no banco de dados$/) do 57 | @acessa_bd = Mysql2::Client.new(:host =>"000.000.00.000", :database =>"base_meu_app", :username =>"root", :password =>"root") 58 | @resultados = @acessa_bd.query("select * from usuarios where nome_usuario = 'BiroBiro'") 59 | @resultados.each do |row| 60 | puts row["nome_usuario"] 61 | expect(row["nome_usuario"]).to eq 'BiroBiro' 62 | end 63 | end 64 | ``` 65 | Então vamos desmembrar esse método: 66 | 67 | ```ruby 68 | @acessa_bd = Mysql2::Client.new(:host =>"000.000.00.000", :database =>"base_meu_app", :username =>"root", :password =>"root") 69 | 70 | Dentre os diversos métodos que o Mysql2 tem, o Client é um que, instanciando, eu tenho que passar os parâmetros: 71 | :host => devemos pegar esse acesso do host de QA; 72 | :database => O nome do banco que estamos trabalhando (qa, stg, flube); 73 | :username => Do banco de dados; 74 | :password => Do banco de dados. 75 | 76 | Com apenas essas informações e claro, com o acesso permitido, conseguimos conectar com o banco já na nossa automação. E isso é bom, porque nos da garantia de raalizar as ações que tanto almejamos (select, alter, delete, etc.). 77 | ``` 78 | 79 | ```ruby 80 | @resultados = @acessa_bd.query("select * from usuarios where nome_usuario = 'BiroBiro'") 81 | 82 | Nesse caso não tem muito o que traduzir certo, estamos ja realizando um select na tabela usuarios com where no campo nome_usuario. 83 | ``` 84 | 85 | ```ruby 86 | @resultados.each do |row| 87 | puts row["nome_usuario"] 88 | expect(row["nome_usuario"]).to eq 'BiroBiro' 89 | end 90 | 91 | Nesse caso criamos um each setando o parâmetro |row| (coluna) para que consigamos realizar ações através de alguma coluna específica, e no nosso caso, estamos dando um print na tela na coluna nome_usuario e logo em seguida estamos dando um expect para garantir que o a coluna nome_usuario possua o valor 'BiroBiro'. Caso tenha algo diferente disso, o teste vai quebrar. 92 | ``` 93 | 94 | Bem, o mesmo se aplica para Alter, Delete e todas as outras ações que realizamos no banco de dados. Podemos criar queries mais sofisticadas, e conseguir trabalhar com o expect para validar se o que esperamos é exatamente aquilo que registramos. 95 | 96 | No próximo vou falar um pouco mais sobre outra gem interessante para acesso ao banco de dados. 97 | 98 | Enjoy. 99 | -------------------------------------------------------------------------------- /CronsForadoControle/um-wait-diferente.md: -------------------------------------------------------------------------------- 1 | # Um Wait diferente. 2 | 3 | Bem, imaginem a seguinte situação que se vocês ainda não passaram por ela, com certeza em algum momento vão se deparar com aqueles testes onde dependemos de uma cron rodando para ativar as coisas, por exemplo, ativação de plano de telefone (péssimo eu sei). Nas andanças pelo github, um colega de trabalho achou uma gem chamada [WaitUtil](https://github.com/rubytools/waitutil), que me deixa ter o controle de fazer refresh a cada X tempo entrando em um condicional caso eu alcance um objetivo. 4 | 5 | Para instalar a gem, basta: 6 | 7 | ```ruby 8 | gem install waitutil 9 | ``` 10 | Só lembrando que podemos deixar essa gem no nosso Gemfile caso faça sentido essa gem pra ti. 11 | 12 | ```ruby 13 | source 'https://rubygems.org' 14 | 15 | gem 'waitutil', '~> 0.2.1' 16 | ``` 17 | 18 | Não esquecer que para utilizar, no env temos que colocar também o chamado da gem: 19 | 20 | ```ruby 21 | require 'waitutil' 22 | ``` 23 | 24 | Para utilizar é bem simples, no momento em que tivermos que "esperar" para ativar ou esperar algum elemento na tela, devemos utilizar: 25 | 26 | ```ruby 27 | WaitUtil.wait_for_condition("o que deve acontecer!!!", :timeout_sec => 30, :delay_sec => 1) do 28 | expect(page).to have_content 'Ativo' 29 | end 30 | ``` 31 | 32 | Explicando agora: 33 | 34 | ```ruby 35 | "o que deve acontecer!!!" é apenas uma string que indica qual é a validação que você espera, por exemplo: "esperar o plano de dados estar ativo.". 36 | 37 | :timeout_sec => 30 é o tempo que vai ficar tentando até dar time out. Conversem com os amigos devs para ver mais ou menos o tempo que se leva para a cron rodar e ativar o plano, para não ficar colocando um tempo muito grande e ficar com um falso positivo ok. 38 | 39 | :delay_sec => 1 é o tempo de tentativa, ou seja, a cada 1 segundo, ele faz refresh na tela. 40 | 41 | expect(page).to have_content 'Ativo' é a validação que quero fazer, no caso, de 1 em 1 segundo ele faz um expect procurando pela palavra "Ativo" na tela. 42 | ``` 43 | Bem, é bem isso! ajuda bastante em alguns casos! -------------------------------------------------------------------------------- /DebugComPry/cucumber/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'capybara', '~> 2.17' 4 | gem 'cucumber', '~> 3.1' 5 | gem 'selenium-webdriver', '~> 3.9' 6 | gem 'pry', '~> 0.12.2' 7 | gem 'rspec', '~> 3.8' 8 | -------------------------------------------------------------------------------- /DebugComPry/cucumber/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.5.2) 5 | public_suffix (>= 2.0.2, < 4.0) 6 | backports (3.11.4) 7 | builder (3.2.3) 8 | capybara (2.18.0) 9 | addressable 10 | mini_mime (>= 0.1.3) 11 | nokogiri (>= 1.3.3) 12 | rack (>= 1.0.0) 13 | rack-test (>= 0.5.4) 14 | xpath (>= 2.0, < 4.0) 15 | childprocess (0.9.0) 16 | ffi (~> 1.0, >= 1.0.11) 17 | coderay (1.1.2) 18 | cucumber (3.1.2) 19 | builder (>= 2.1.2) 20 | cucumber-core (~> 3.2.0) 21 | cucumber-expressions (~> 6.0.1) 22 | cucumber-wire (~> 0.0.1) 23 | diff-lcs (~> 1.3) 24 | gherkin (~> 5.1.0) 25 | multi_json (>= 1.7.5, < 2.0) 26 | multi_test (>= 0.1.2) 27 | cucumber-core (3.2.1) 28 | backports (>= 3.8.0) 29 | cucumber-tag_expressions (~> 1.1.0) 30 | gherkin (~> 5.0) 31 | cucumber-expressions (6.0.1) 32 | cucumber-tag_expressions (1.1.1) 33 | cucumber-wire (0.0.1) 34 | diff-lcs (1.3) 35 | ffi (1.9.25) 36 | gherkin (5.1.0) 37 | method_source (0.9.2) 38 | mini_mime (1.0.1) 39 | mini_portile2 (2.3.0) 40 | multi_json (1.13.1) 41 | multi_test (0.1.2) 42 | nokogiri (1.8.5) 43 | mini_portile2 (~> 2.3.0) 44 | pry (0.12.2) 45 | coderay (~> 1.1.0) 46 | method_source (~> 0.9.0) 47 | public_suffix (3.0.3) 48 | rack (2.0.6) 49 | rack-test (1.1.0) 50 | rack (>= 1.0, < 3) 51 | rspec (3.8.0) 52 | rspec-core (~> 3.8.0) 53 | rspec-expectations (~> 3.8.0) 54 | rspec-mocks (~> 3.8.0) 55 | rspec-core (3.8.0) 56 | rspec-support (~> 3.8.0) 57 | rspec-expectations (3.8.2) 58 | diff-lcs (>= 1.2.0, < 2.0) 59 | rspec-support (~> 3.8.0) 60 | rspec-mocks (3.8.0) 61 | diff-lcs (>= 1.2.0, < 2.0) 62 | rspec-support (~> 3.8.0) 63 | rspec-support (3.8.0) 64 | rubyzip (1.2.2) 65 | selenium-webdriver (3.141.0) 66 | childprocess (~> 0.5) 67 | rubyzip (~> 1.2, >= 1.2.2) 68 | xpath (3.2.0) 69 | nokogiri (~> 1.8) 70 | 71 | PLATFORMS 72 | ruby 73 | 74 | DEPENDENCIES 75 | capybara (~> 2.17) 76 | cucumber (~> 3.1) 77 | pry (~> 0.12.2) 78 | rspec (~> 3.8) 79 | selenium-webdriver (~> 3.9) 80 | 81 | BUNDLED WITH 82 | 1.16.6 83 | -------------------------------------------------------------------------------- /DebugComPry/cucumber/cucumber.yml: -------------------------------------------------------------------------------- 1 | ##YAML Template 2 | --- 3 | default: -p chrome -p qa-environment 4 | ci: -p json_report -p chrome_headless -p qa-environment 5 | html_report: --format pretty --format html --out=features_report.html 6 | json_report: --format pretty --format json --out=report/features_report.json 7 | chrome: BROWSER=chrome 8 | chrome_headless: BROWSER=chrome_headless 9 | qa-environment: ENVIRONMENT_TYPE=qa-env 10 | staging-environment: ENVIRONMENT_TYPE=staging-env 11 | prod-environment: ENVIRONMENT_TYPE=prod-env -------------------------------------------------------------------------------- /DebugComPry/cucumber/features/specs/simple-example-to-test.feature: -------------------------------------------------------------------------------- 1 | Feature: Simple test to try to use pry 2 | 3 | I as QA 4 | Would like to test a simple example 5 | 6 | @simple 7 | Scenario: Access and asserts 8 | Given I access the store 9 | When I click on my account 10 | Then I see the obrigatory fields to login -------------------------------------------------------------------------------- /DebugComPry/cucumber/features/step_definitions/simple-example.rb: -------------------------------------------------------------------------------- 1 | Given("I access the store") do 2 | visit '/' 3 | binding.pry 4 | end 5 | 6 | When("I click on my account") do 7 | expect(page).to have_content 'My Account' 8 | click_link 'My Account' 9 | end 10 | 11 | Then("I see the obrigatory fields to login") do 12 | expect(page).to have_content 'Username' 13 | expect(page).to have_content 'Password' 14 | end -------------------------------------------------------------------------------- /DebugComPry/cucumber/features/support/config/hooks.rb: -------------------------------------------------------------------------------- 1 | Before do 2 | Capybara.configure do |config| 3 | config.default_driver = :selenium 4 | config.app_host = CONFIG['url'] 5 | end 6 | Capybara.default_max_wait_time = 10 7 | end 8 | 9 | After do 10 | unless BROWSER.eql?('chrome') 11 | Capybara.current_session.driver.quit 12 | end 13 | end 14 | 15 | After do |scenario| 16 | scenario_name = scenario.name 17 | file_name = scenario_name.gsub(' ', '_') 18 | img_path = "results/images/" 19 | shot = "#{img_path}/#{file_name.downcase!}.png" 20 | page.save_screenshot(shot) 21 | embed(shot, 'image/png', 'Clique aqui pra ver o PRINT :)') 22 | end -------------------------------------------------------------------------------- /DebugComPry/cucumber/features/support/config/prod-env.yaml: -------------------------------------------------------------------------------- 1 | url: 'https://prod-env.qa.com' -------------------------------------------------------------------------------- /DebugComPry/cucumber/features/support/config/qa-env.yaml: -------------------------------------------------------------------------------- 1 | url: 'http://store.demoqa.com' -------------------------------------------------------------------------------- /DebugComPry/cucumber/features/support/config/staging-env.yaml: -------------------------------------------------------------------------------- 1 | url: 'https://staging-env.qa.com' -------------------------------------------------------------------------------- /DebugComPry/cucumber/features/support/env.rb: -------------------------------------------------------------------------------- 1 | require 'capybara' 2 | require 'capybara/dsl' 3 | require 'capybara/cucumber' 4 | require 'selenium-webdriver' 5 | require 'pry' 6 | require 'rspec' 7 | 8 | BROWSER = ENV['BROWSER'] 9 | ENVIRONMENT_TYPE = ENV['ENVIRONMENT_TYPE'] 10 | 11 | ## variable which loads the data file according to the environment 12 | CONFIG = YAML.load_file(File.dirname(__FILE__) + "/config/#{ENVIRONMENT_TYPE}.yaml") 13 | 14 | ## Register driver according with browser chosen 15 | Capybara.register_driver :selenium do |app| 16 | if BROWSER.eql?('chrome') 17 | options = ::Selenium::WebDriver::Chrome::Options.new 18 | options.add_argument('--window-size=1920,1080') 19 | Capybara::Selenium::Driver.new(app, browser: :chrome, options: options) 20 | elsif BROWSER.eql?('chrome_headless') 21 | options = ::Selenium::WebDriver::Chrome::Options.new 22 | options.add_argument('--headless') 23 | options.add_argument('--no-sandbox') 24 | options.add_argument('--disable-dev-shm-usage') 25 | options.add_argument('--window-size=1920,1080') 26 | Capybara::Selenium::Driver.new(app, browser: :chrome, options: options) 27 | end 28 | end -------------------------------------------------------------------------------- /DebugComPry/debug-seus-testes.md: -------------------------------------------------------------------------------- 1 | # Debugar é sempre preciso 2 | 3 | Bem, esse talvez seja o mais simples da série do dia a dia do capybara, porém muitas pessoas que falam comigo sobre automação com capybara por exemplo, me mostram seus testes quebrando sem saber porque em algum ponto da execução, mas sempre executam os mesmos testes para tentar perceber onde que está o problema. E isso é bem chato, e as vezes temos testes tão longos que passamos até horas para tentar entender (com tantas execuções) onde que estão os problemas e sabendo disso, temos uma gem que nos ajuda a fazer o debug e assim não preciso me desesperar tanto olhando para tela. A gem se chama [PRY](https://github.com/pry/pry), que nada mais vai fazer que abrir um IRB (Iterative ruby shell). 4 | 5 | ## Instalando a Gem 6 | 7 | Eu tenho por padrão antes de sair instalando as coisas, vou até o **[rubygems]**(https://rubygems.org/) e procuro pela gem para ver a questão da versão que eu quero utilizar, se ela ta estável, mas pronto, podemos simplesmente instalar ou colocar no Gemfile: 8 | 9 | ```ruby 10 | gem 'pry', '~> 0.12.2' 11 | ``` 12 | Depois dar um **bundle install** ou de forma manual: 13 | 14 | ```ruby 15 | gem install pry -v 0.12.2 16 | ``` 17 | 18 | ## Deixando pronto para utilizar 19 | 20 | Instalou a gem, agora vamos no nosso arquivo **env.rb** e deixar mais ou menos assim: 21 | 22 | ```ruby 23 | require 'capybara' 24 | require 'capybara/dsl' 25 | require 'capybara/cucumber' 26 | require 'selenium-webdriver' 27 | require 'pry' 28 | ``` 29 | 30 | ## Usando =) 31 | 32 | Bem, o uso do **pry** é bem simples e com apenas um comando para que ele pare deixando pronto pra usar, que é ***binding.pry***. Vou colocar uma estrutura básica para exemplificar: 33 | 34 | Exemplo utilizando o pry nos arquivos de steps: 35 | 36 | ```ruby 37 | Given("I access the store") do 38 | visit '/' 39 | binding.pry -- Esse é o comando para a execução do script parar exatamente nesse ponto do teste 40 | end 41 | 42 | When("I click on my account") do 43 | expect(page).to have_content 'My Account' 44 | click_link 'My Account' 45 | end 46 | 47 | Then("I see the obrigatory fields to login") do 48 | expect(page).to have_content 'Username' 49 | expect(page).to have_content 'Password' 50 | end 51 | ``` 52 | 53 | Quando a execução chegar no **binding.pry** no nosso terminal vai aparecer: 54 | 55 | ```shell 56 | cucumber -p chrome -p qa-environment --tags @simple 57 | 58 | Using the chrome and qa-environment profiles... 59 | Feature: Simple test to try to use pry 60 | I as QA 61 | Would like to test a simple example 62 | 63 | From: /Users/thiagopereira/workspace/articles/dia-a-dia-capybara/DegugComPry/cucumber/features/step_definitions/simple-example.rb @ line 3 : 64 | 65 | 1: Given("I access the store") do 66 | 2: visit '/' 67 | => 3: binding.pry 68 | 4: end 69 | 5: 70 | 6: When("I click on my account") do 71 | 7: expect(page).to have_content 'My Account' 72 | 8: click_link 'My Account' 73 | 74 | [1] pry(#)> 75 | ``` 76 | 77 | Nesse caso o que nós temos: 78 | 79 | **=> 3: binding.pry** - Local onde o teste parou e olha que interessante, o que é preciso fazer agora é ***testar*** nossa implementação, e copiar e colar os comandos que estão nos nossos arquivos de steps, por exemplo: 80 | 81 | ```shell 82 | 1: Given("I access the store") do 83 | 2: visit '/' 84 | => 3: binding.pry 85 | 4: end 86 | 5: 87 | 6: When("I click on my account") do 88 | 7: expect(page).to have_content 'My Account' 89 | 8: click_link 'My Account' 90 | 91 | [1] pry(#)> expect(page).to have_content 'My Account' 92 | => true 93 | [2] pry(#)> 94 | ``` 95 | 96 | Nesse caso, o teste foi verdadeiro. 97 | 98 | Obs.: Por mais que seja um debug, precisamos realizar uma ação no terminal e ver como correu no browser em questão e ver se o teste foi executado com sucesso. Um teste legal é quando damos find em algum elemento, por exemplo: 99 | 100 | ```shell 101 | [2] pry(#)> find('#account a') 102 | => # 103 | ``` 104 | 105 | Medonho, eu sei. mas paciência. 106 | 107 | ## Saindo do debug 108 | 109 | Terminou os testes que queria realizar via debug, não esqueçam de passar esses comandos para o projeto viu (normal esquecer), então caso tenha algum sucesso, copia e cole direto no seu arquivo de steps ou onde quer que seja. Nesse caso, temos 3 frentes: **terminal, editor de texto e browser**. 110 | 111 | Terminando, basta dar um **exit**: 112 | 113 | ```shell 114 | [3] pry(#)> exit 115 | @simple 116 | Scenario: Access and asserts # features/specs/simple-example-to-test.feature:7 117 | Given I access the store # features/step_definitions/simple-example.rb:1 118 | When I click on my account # features/step_definitions/simple-example.rb:6 119 | Then I see the obrigatory fields to login # features/step_definitions/simple-example.rb:11 120 | 121 | 1 scenario (1 passed) 122 | 3 steps (3 passed) 123 | 7m16.012s 124 | ``` 125 | 126 | E pronto, termina a execução. E olha que interessante, o tempo que foi feito essa execução foi de sete minutos, justamente o tempo que levei escrevendo e tirando prints rsrsrs . 127 | 128 | 129 | ## Dica útil 130 | 131 | Não esqueçam de tirar o debug depois que terminarem =) senão o teste vai ficar parado e vou falar que esquecer e enviar pra master e o ci ficar preso por conta de debug **Não é legal** #quenunca. 132 | 133 | Enfim, obrigado por acompanhar até aqui, qualquer dúvida, gritem ai. 134 | -------------------------------------------------------------------------------- /Elementos/id-dinamico-classes-iguais.md: -------------------------------------------------------------------------------- 1 | # Um problema bem chato não é mesmo??? 2 | 3 | Bom, quando eu aprendi a automatizar testes eu fui condicionado a buscar elementos da seguinte maneira: "SEMPRE BUSQUE PELO ID" e se não tiver ID, botão direito -> copiar CSS ou Xpath. E com o passar dos tempos eu condenava os devs quando eles não colocavam IDs e fazia um mimimi lascado (vocês sabem do que eu to falando rs). 4 | 5 | Ai passou o tempo e aprendemos que buscar elemento usando um seletor (jQuery por exemplo) é uma solução legal para pegar o elemento de forma mais certeira. Vou dar um exemplo de como buscamos elementos com jQuery: 6 | 7 | ```ruby 8 | Pense no seguinte elemento, considerando que não temos ID : 9 | 10 | 11 | 12 | Então estamos falando que temos um campo de input onde eu vou colocar o Primeiro Nome OK, então no console do navegador para encontrar esse elemento fazemos da seguinte maneira: 13 | $('.field-input-first-name') 14 | 15 | 16 | Quando eu passar o mouse em cima desse resultado, ele vai deixar identificar esse elemento. Depois pegamos essa classe e passamos no find por exemplo.: 17 | 18 | find(:css, '.field-input-first-name').set("Primeiro nome do Cliente") 19 | ``` 20 | 21 | Ai com o passar dos anos e sendo criados diversos frameworks modernos de desenvolvimento Front-End (ember, React, Bootstrap, etc) caímos no seguinte cenário: Ids dinâmicos e classes iguais (por tipo de componente). Aí virou um Eru nos acuda, bateu um desespero na galera, e muitos chegam pra mim e falam "E agora, o que eu faço nesse contexto?". A documentação do capybara nos fornece um comando chamado "all", que você pega e passa o índice (posição do elemento) e depois passa a iteragir com o elemento, ficando dessa forma: 22 | 23 | ```ruby 24 | Considerando que eu esteja em um formulário e o componente utilizado tem uma classe e os ids são dinâmicos. 25 | 26 | 27 | No console do navegador vamos buscar pela classe: 28 | 29 | $('.field-input') 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | No nosso arquivo de step podemos pegar o índice e passar: 38 | 39 | all(:css, '.field-input')[0].set("Primeiro nome do Cliente"), onde [0] é o índice e simboliza a primeira posição. 40 | ``` 41 | Vai funcionar? Sim!!! Mas vai ficar feio pra caramba! Então temos uma solução, de usar o XPATH para poder trabalhar? 42 | 43 | Ai vem a mesma escola que aprendeu que XPATH é uma porcaria e etc. Sim, é uma porcaria porque você aprendeu a clicar com o botão direito do mouse e copiar o xpath ficando desse jeito: 44 | 45 | ```ruby 46 | //div/a/a/a/span/div/div/input[10]/div/input[0] 47 | ``` 48 | 49 | Isso é feio demais, e se mudar qualquer coisa no meu html, ele vai varrer e não vai achar meu elemento. 50 | 51 | Mas tem uma forma elegante de trabalhar nesse caso, usando XPATH e observando direito meu HTML. E o segredo para quem desenvolve nesses frameworks é que sempre terá um atributo no meu HTML que será diferente para cada elemento, no nosso exemplo, temos o atributo "name" e vamos fazer da seguinte forma: 52 | 53 | ```ruby 54 | find(:xpath, '//input[@name="first-name"]').set("Primeiro nome do Cliente") 55 | ``` 56 | 57 | E pronto, ficou clean e o elemento pode mudar de posição, que ele não vai sofrer alteração, pois sempre será encontrado, porque o name para cada elemento é único. Pra colocar no SitePrism é tranquilo também: 58 | 59 | ```ruby 60 | class MeusElementos