Open29
RSpecé¢é£ðïŒäžéšGitHub Actionså«ãïŒ
éçºç°å¢
ã«ããŽãªãŒ | 䜿çšæè¡ |
---|---|
ããã³ããšã³ã | Rails 7.1.3.4, TailwindCSS, DaisyUI Javascript |
ããã¯ãšã³ã | Rails 7.1.3.4 (ruby 3.2.3) |
ã€ã³ãã© | heroku / AmazonS3 |
DB | MySQL |
éçºç°å¢ | Docker |
è³æ
factory boté¢é£
GitHub Actionsã®å°å ¥ã®æµãã¯ãã¡ã
åèè³æ
ãã¡ã€ã«äœæ
RSpecèšå®ãã¡ã€ã«äœæ
$ docker compose exec web bundle exec rails g rspec:install
ã¢ãã«ã¹ããã¯äœæ
$ docker compose exec web bundle exec rails generate rspec:model User #ã¢ãã«åã¯åæ°é æå倧æå
factory botã®ãã¡ã€ã«äœæ
$ docker compose exec web bundle exec rails g factory_bot:model user
- ãªãããããå®è¡ãããš
test/factories/*.rb
ã«äœæããã - ãã äžèšã®ãã¡ã€ã«ãèªåã§ããŒãããããããã®ã§åé¡ãªãããïŒ
factories.rb
test/factories.rb
spec/factories.rb
factories/*.rb
test/factories/*.rb
spec/factories/*.rb
spec/rails_helper.rbã§ã®èšå®å¿ãã
1) User ååãã¡ãŒã«ãããããã¹ã¯ãŒãã¯3æå以äžã§ããã°æå¹ã§ããããš
Failure/Error: user = build(:user)
NoMethodError:
undefined method `build' for #<RSpec::ExampleGroups::User "ååãã¡ãŒã«ãããããã¹ã¯ãŒãã¯3æå以äžã§ããã°æå¹ã§ããããš" (./spec/models/user_spec.rb:4)>
# ./spec/models/user_spec.rb:5:in `block (2 levels) in <top (required)>'
- buildã£ãŠãªãã§ããããšèšããã
èšå®ã®è¿œå
#spec/rails_helper.rb
config.include FactoryBot::Syntax::Methods
- ã§ããðââïž
ã¬ãã¬ããžè¡šç€ºã®gemã®èŠæ¹
- VScodeã®Live Serverã䜿çš
- ãã¡ã€ã«ã¯
coverage/index.html
ã§Go LiveããïŒVScodeå³äžïŒ
- ãã®ãã¡ã€ã«ã¯
.gitignore
ã«è¿œå ããŠãããŸã
Userã®enumïŒä»»æé ç®ïŒ
- 決ãŸã£ãå€ã§å ¥åã§ãããã®ãã¹ã
it 'äžä»£ãšæ§å¥ãå
¥åã§ããããš' do
user = build(:user)
user.age = (0..5).to_a.sample
user.gender = (0..1).to_a.sample
expect(user).to be_valid
end
- èšå®ããŠããèŠçŽ ãã©ã³ãã ã§åãåºã圢ã«ããŠã¿ã
RSpecã®å°å ¥
è³æ
ãã®ä»è³æ
DBããã¹ãç°å¢ã§å¯Ÿå¿
- name: Database create and migrate
run: |
cp config/database.ci.yml config/database.yml
bundle exec rake db:create
bundle exec rake db:migrate
rake aborted!
ActiveRecord::AdapterNotSpecified: The `development` database is not configured for the `development` environment. (ActiveRecord::AdapterNotSpecified)
Available database configurations are:
- developmentç°å¢ã®èšå®ãäžè¶³ããŠããããšãåå
ãã¹ãç°å¢ã®DBã«èšå®ããŠã¿ã
- name: Database create and migrate
run: |
cp config/database.ci.yml config/database.yml
RAILS_ENV=test bundle exec rake db:create
RAILS_ENV=test bundle exec rake db:migrate
127.0.0.1:3306
ã«ããïŒChatGPTã»NGïŒ
config/database.ci.ymlã®localhostã®èšå®ãPlease check your database configuration and ensure there is a valid connection to your database.
Couldn't create 'rails7-mysql' database. Please check your configuration.
rake aborted!
ActiveRecord::DatabaseConnectionError: There is an issue connecting with your hostname: 127.0.0.1. (ActiveRecord::DatabaseConnectionError)
#...
Caused by:
Mysql2::Error::ConnectionError: Can't connect to MySQL server on '127.0.0.1:3306' (111) (Mysql2::Error::ConnectionError)
/home/runner/work/metime-meals/metime-meals/vendor/bundle/ruby/3.2.0/gems/mysql2-0.5.6/lib/mysql2/client.rb:97:in `connect'
/home/runner/work/metime-meals/metime-meals/vendor/bundle/ruby/3.2.0/gems/mysql2-0.5.6/lib/mysql2/client.rb:97:in `initialize'
- ãã¡ãããã®ã§
127.0.0.1
ã«æ»ããŸã - äžèšã¿ããšãã£ãŠãããªã®ã ã
rubocop,RSpecãdeployã®needsã«
倱æäŸ
deploy:
if: github.ref == 'refs/heads/main'
needs: rubocop, rspec
- Invalid workflow file: .github/workflows/deploy.yml#L64
The workflow is not valid. .github/workflows/deploy.yml (Line: 64, Col: 12): Job 'deploy' depends on unknown job 'rubocop, rspec'.
æåäŸ
deploy:
if: github.ref == 'refs/heads/main'
needs:
- rubocop
- rspec
- é å圢åŒã«ããŠãããŸã
databaseïŒmyapp_testïŒã®åååãããïŒãšããããä»æ¥ã¯ãããŸã§ïŒ
#config/database.ci.yml
test:
adapter: mysql2
charset: utf8mb4
collation: utf8mb4_bin
encoding: utf8mb4
database: myapp_test
host: 127.0.0.1
username: root
password: password
reconnect: true
#.github/workflows/deploy.yml
name: rubocop, rspec, deploy
on:
push:
branches:
jobs:
rspec:
runs-on: ubuntu-latest
timeout-minutes: 10
services:
mysql:
image: mysql:8.0
ports:
- 3307:3306
env:
MYSQL_ROOT_PASSWORD: password
MYSQL_ROOT_HOST: '%'
options: --health-cmd "mysqladmin ping -h 127.0.0.1" --health-interval 20s --health-timeout 10s --health-retries 10
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Bundler and gem install
run: |
gem install bundler
bundle install --jobs 4 --retry 3 --path vendor/bundle
- name: Wait for MySQL
run: sleep 15
- name: Database create and migrate
run: |
cp config/database.ci.yml config/database.yml
bundle exec rails db:create RAILS_ENV=test
bundle exec rails db:migrate RAILS_ENV=test
- name: Run rspec
run: bundle exec rspec
rubocop:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Run rubocop
run: bundle exec rubocop -a
deploy:
if: github.ref == 'refs/heads/main'
needs:
- rubocop
- rspec
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: akhileshns/heroku-deploy@v3.13.15
with:
heroku_api_key: ${{secrets.HEROKU_API_KEY}}
heroku_app_name: ${{ secrets.HEROKU_APP_NAME }}
heroku_email: ${{ secrets.HEROKU_EMAIL }}
presence: true
ã§ã¯ãªããã©null:false
ã§ãããã®ã«ã€ããŠ
ã³ãŒã
#test/factories/bookmarks.rb
FactoryBot.define do
factory :bookmark do
association :user
association :post
end
end
#spec/models/bookmark_spec.rb
context 'ãŠãŒã¶ãŒãšæ²ç€ºæ¿ã®çµã¿åããããŠããŒã¯ã§ãªãå Žå' do
it 'ç¡å¹ã§ããããš' do
bookmark = create(:bookmark)
new_bookmark = build(:bookmark, user: bookmark.user, post: bookmark.post)
new_bookmark.valid?
expect(new_bookmark.errors[:user_id]).to include('ã¯ãã§ã«ååšããŸã'), 'bookmarkãšuserã®ãŠããŒã¯ããªããŒã·ã§ã³ãèšå®ãããŠããŸãã'
end
end
ãšã©ãŒæ
1) Bookmark ãŠãŒã¶ãŒãšæ²ç€ºæ¿ã®çµã¿åããããŠããŒã¯ã§ãªãå Žå ç¡å¹ã§ããããš
Failure/Error: bookmark = create(:bookmark)
ActiveRecord::NotNullViolation:
Mysql2::Error: Column 'latitude' cannot be null
# /usr/local/bundle/gems/mysql2-0.5.6/lib/mysql2/client.rb:151:in `_query'
# /usr/local/bundle/gems/mysql2-0.5.6/lib/mysql2/client.rb:151:in `block in query'
# /usr/local/bundle/gems/mysql2-0.5.6/lib/mysql2/client.rb:150:in `handle_interrupt'
# /usr/local/bundle/gems/mysql2-0.5.6/lib/mysql2/client.rb:150:in `query'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/evaluation.rb:15:in `create'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/strategy/create.rb:12:in `block in result'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/strategy/create.rb:9:in `result'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/factory.rb:45:in `run'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/factory_runner.rb:29:in `block in run'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/factory_runner.rb:28:in `run'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/strategy/create.rb:5:in `association'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/evaluator.rb:33:in `association'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/attribute/association.rb:19:in `block in to_proc'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/evaluator.rb:75:in `instance_exec'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/evaluator.rb:75:in `block in define_attribute'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/attribute_assigner.rb:59:in `get'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/attribute_assigner.rb:16:in `block (2 levels) in object'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/attribute_assigner.rb:15:in `each'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/attribute_assigner.rb:15:in `block in object'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/attribute_assigner.rb:14:in `object'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/evaluation.rb:10:in `object'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/strategy/create.rb:9:in `result'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/factory.rb:45:in `run'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/factory_runner.rb:29:in `block in run'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/factory_runner.rb:28:in `run'
# /usr/local/bundle/gems/factory_bot-6.5.0/lib/factory_bot/strategy_syntax_method_registrar.rb:28:in `block in define_singular_strategy_method'
# ./spec/models/bookmark_spec.rb:13:in `block (3 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# Mysql2::Error:
# Column 'latitude' cannot be null
# /usr/local/bundle/gems/mysql2-0.5.6/lib/mysql2/client.rb:151:in `_query'
解決ç
- Postãã¡ã¯ããªãŒã«
longitude
ãšlatitude
ãè¿œå ãã
#test/factories/posts.rb
FactoryBot.define do
factory :post do
sequence(:restaurant_name) { |n| "ã¿ã€ãã«#{n}" }
sequence(:body) { |n| "æ¬æ#{n}" }
sequence(:address) { |n| "äœæ#{n}" }
genre { [0, 1, 2, 3, 4, 10, 11, 20, 21, 99].sample }
rating { [0, 1, 2, 3, 4].sample }
latitude { 35.6895 }
longitude { 139.6917 }
association :user
end
end
describe/context/it
describe
- ãã¹ãã®å¯Ÿè±¡ã説æ
- ã¢ãã«ã®å Žåã¯ã¯ã©ã¹åãã¡ãœããå
- ã·ã¹ãã ã¹ããã¯ã®å Žåã¯æ©èœåïŒããŠãŒã¶ãŒããã®æ³šæããªã©ãå€ãïŒ
context
- ç¶æ³ãæ¡ä»¶ã説æ
- ãããã®å Žåããªã©
- contextã䜿ãå Žåãç¶æ³ãæ¡ä»¶ãæå®ããã³ãŒããå¿ èŠãªããšãå€ã
it
- itã§ã¯æåŸ
ããåäœã»çµæã説æãã
- ãããã§ããããšãããããã§ããããšããªã©ã§çµããè¡šçŸã«ãªãããšãå€ã
- ãæ£ããããšãã®ããã«äœãæ£ãããããããªãæãã§æžããªã
- å ·äœçã«ããããªãããã«ãªãããšãã£ãæãã§æžã
- æºåã¯
let
ãbefore
ã®äžã«æžãããšã§ãæºåã»å®è¡ã»æ€èšŒã¯åé¢ãããäžãè·é¢ã¯è¿ã
- åŒçšå ïŒã³ãŒãã¬ãã¥ãŒã§åŠã¶ Ruby on Rails 第äºçïŒSG Rails
ãã¹ãã³ãŒãã®æ³šæç¹
- ãã¹ãã®èª¬æã¯å ·äœçã«æžã
- æåŸ
å€ã«äœ¿ãå€ã¯åããã¹ãã³ãŒãå
ã§æºåãã(pp.70-72)
- FactoryBotã§äœãéã¯æåŸ å€ãæå®
- ãŠãŒã¶ãŒã«è¡šç€ºãããç»é¢ãæ³å®ãããã¹ããæžã(pp.72-73)
- ç»é²ãããå 容ã詳现ç»é¢ã«ã¢ã¯ã»ã¹ããé衚瀺ã§ãããã確èª
- é
延è©äŸ¡ã䜿ãå Žå
before
ã䜿ã- let/let!ã䜿çšããããšã§ã¹ã³ãŒããåºããªãå¯èªæ§ãäžãã
-
it~do
ãšããæžãæ¹ãè¯ã - ã€ã³ã¹ã¿ã³ã¹å€æ°ã䜿ã
- å ¥åå€ãæåŸ å€ã¯ãã¿æžãããã
- é »åºããå®çŸ©ã¯traitã䜿ã
- ããããªãããšãã ãã®ãã¹ãã¯äœæããªããåæã«ã§ããå Žåã®ãã¹ããå®è£ ããã
- ãã¹ãããŒã¿ã®åœåã¯ãããããã
- äžèŠãªå€ïŒ=æ€èšŒã«äžèŠãªå€ïŒã¯ãã¹ãã«å«ããªã
- åŒçšå ïŒã³ãŒãã¬ãã¥ãŒã§åŠã¶ Ruby on Rails 第äºçïŒSG Rails
selenium-webdriver
ã«ã€ããŠ
- Web ãã©ãŠã¶ã®æäœãèªååããããã®ãã¬ãŒã ã¯ãŒã¯
- Web ã¢ããªã±ãŒã·ã§ã³ã® UI ãã¹ããèªååããç®çã§éçº
ã·ã¹ãã ã¹ããã¯ïŒéçºç°å¢ïŒDockerïŒ
Gemã®å°å ¥
# Gemfile
group :test do
gem 'capybara'
gem 'selenium-webdriver'
gem "webdrivers"
end
webdriverã®èšå®
- ãã¹ããå®è¡ããç°å¢ã®èšå®
# spec/rails_helper.rb
#...
# ãã¡ã€ã«ã®èªã¿èŸŒã¿èšå®
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }
#...
RSpec.configure do |config|
#...
config.before(:each, type: :system) do
driven_by :remote_chrome
Capybara.server_host = IPSocket.getaddress(Socket.gethostname)
Capybara.server_port = 4444
Capybara.app_host = "http://#{Capybara.server_host}:#{Capybara.server_port}"
Capybara.ignore_hidden_elements = false
end
#...
end
capybaraã®èšå®
# spec/support/capybara.rb
Capybara.register_driver :remote_chrome do |app|
options = Selenium::WebDriver::Chrome::Options.new
options.add_argument('no-sandbox')
options.add_argument('headless')
options.add_argument('disable-gpu')
options.add_argument('window-size=1680,1050')
Capybara::Selenium::Driver.new(app, browser: :remote, url: ENV['SELENIUM_DRIVER_URL'], capabilities: options)
end
- webdriveräžã§ã®ãã¹ãã«å¿ èŠãªæäœãããããããæžãããšãã§ãã
- 䜿ããRSpecå ¥éã»ãã®4ãã©ããªãã©ãŠã¶æäœãèªç±èªåšïŒéåŒãCapybara倧èŸå žã #Ruby - Qiita
äžèšã®èšå®ã®ã¿ã ãšäžèšãšã©ãŒ
1) ãŠãŒã¶ãŒç»é² æ£ããã¿ã€ãã«ã衚瀺ãããŠããããš
Got 0 failures and 2 other errors:
1.1) Failure/Error: visit '/users/new'
Errno::ECONNREFUSED:
Failed to open TCP connection to 127.0.0.1:4444 (Connection refused - connect(2) for "127.0.0.1" port 4444)
# /usr/local/bundle/gems/net-http-0.4.1/lib/net/http.rb:1603:in `initialize'
# /usr/local/bundle/gems/net-http-0.4.1/lib/net/http.rb:1603:in `open'
# /usr/local/bundle/gems/net-http-0.4.1/lib/net/http.rb:1603:in `block in connect'
# /usr/local/bundle/gems/timeout-0.4.1/lib/timeout.rb:186:in `block in timeout'
# /usr/local/bundle/gems/timeout-0.4.1/lib/timeout.rb:193:in `timeout'
# /usr/local/bundle/gems/net-http-0.4.1/lib/net/http.rb:1601:in `connect'
# /usr/local/bundle/gems/net-http-0.4.1/lib/net/http.rb:1580:in `do_start'
# /usr/local/bundle/gems/net-http-0.4.1/lib/net/http.rb:1575:in `start'
# /usr/local/bundle/gems/selenium-webdriver-4.22.0/lib/selenium/webdriver/remote/http/default.rb:65:in `start'
# /usr/local/bundle/gems/selenium-webdriver-4.22.0/lib/selenium/webdriver/remote/http/default.rb:59:in `http'
# /usr/local/bundle/gems/capybara-3.40.0/lib/capybara/selenium/patches/persistent_client.rb:14:in `http'
# /usr/local/bundle/gems/selenium-webdriver-4.22.0/lib/selenium/webdriver/remote/http/default.rb:118:in `response_for'
# /usr/local/bundle/gems/selenium-webdriver-4.22.0/lib/selenium/webdriver/remote/http/default.rb:75:in `request'
# /usr/local/bundle/gems/selenium-webdriver-4.22.0/lib/selenium/webdriver/remote/http/common.rb:67:in `call'
# /usr/local/bundle/gems/selenium-webdriver-4.22.0/lib/selenium/webdriver/remote/bridge.rb:635:in `execute'
# /usr/local/bundle/gems/selenium-webdriver-4.22.0/lib/selenium/webdriver/remote/bridge.rb:76:in `create_session'
# /usr/local/bundle/gems/selenium-webdriver-4.22.0/lib/selenium/webdriver/common/driver.rb:323:in `block in create_bridge'
# /usr/local/bundle/gems/selenium-webdriver-4.22.0/lib/selenium/webdriver/common/driver.rb:322:in `create_bridge'
# /usr/local/bundle/gems/selenium-webdriver-4.22.0/lib/selenium/webdriver/common/driver.rb:73:in `initialize'
# /usr/local/bundle/gems/selenium-webdriver-4.22.0/lib/selenium/webdriver/remote/driver.rb:38:in `initialize'
# /usr/local/bundle/gems/selenium-webdriver-4.22.0/lib/selenium/webdriver/common/driver.rb:57:in `new'
# /usr/local/bundle/gems/selenium-webdriver-4.22.0/lib/selenium/webdriver/common/driver.rb:57:in `for'
# /usr/local/bundle/gems/selenium-webdriver-4.22.0/lib/selenium/webdriver.rb:89:in `for'
# /usr/local/bundle/gems/capybara-3.40.0/lib/capybara/selenium/driver.rb:75:in `browser'
# /usr/local/bundle/gems/capybara-3.40.0/lib/capybara/selenium/driver.rb:95:in `visit'
# /usr/local/bundle/gems/capybara-3.40.0/lib/capybara/session.rb:281:in `visit'
# /usr/local/bundle/gems/capybara-3.40.0/lib/capybara/dsl.rb:52:in `call'
# /usr/local/bundle/gems/capybara-3.40.0/lib/capybara/dsl.rb:52:in `visit'
# ./spec/system/users_spec.rb:3:in `block (2 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# Errno::ECONNREFUSED:
# Connection refused - connect(2) for "127.0.0.1" port 4444
# /usr/local/bundle/gems/net-http-0.4.1/lib/net/http.rb:1603:in `initialize'
compose.ymlã«äžèšè¿œèš
# compose.yml
environment:
TZ: Asia/Tokyo
# ã·ã¹ãã ã¹ããã¯ã§è¿œèš
SELENIUM_DRIVER_URL: http://chrome:4444/wd/hub
# ãããŸã§
ports:
- "3000:3000"
depends_on:
db:
condition: service_healthy
# ã·ã¹ãã ã¹ããã¯ã§è¿œèš
chrome:
image: seleniarm/standalone-chromium:latest
ports:
- 4444:4444
# ãããŸã§
- ã³ã³ããç«ã¡äžãçŽããšè§£æ¶
-
localhost:4444
ãéããšSelenium Gridã®ããŒãžãéããŸã
åè
ãã¹ãã±ãŒã¹ããã®éåŒããå¯èœ
ã¯ã©ãã·ã¥ã®å¯ŸåŠæ³
- ãã©ãŠã¶ã®ãµã€ãºãå°ãããã
1) Users ãã°ã€ã³åŸ ãŠãŒã¶ãŒç·šé ãã©ãŒã ã®å
¥åå€ãæ£åžž ãŠãŒã¶ãŒã®ç·šéãæåãã
Got 0 failures and 4 other errors:
1.1) Failure/Error: visit root_path
Selenium::WebDriver::Error::UnknownError:
unknown error: session deleted because of page crash
from unknown error: cannot determine loading status
from tab crashed
(Session info: chrome-headless-shell=121.0.6167.85)
# /usr/local/bundle/gems/selenium-webdriver-4.25.0/lib/selenium/webdriver/remote/response.rb:63:in `add_cause'
# /usr/local/bundle/gems/selenium-webdriver-4.25.0/lib/selenium/webdriver/remote/response.rb:41:in `error'
# /usr/local/bundle/gems/selenium-webdriver-4.25.0/lib/selenium/webdriver/remote/response.rb:52:in `assert_ok'
# /usr/local/bundle/gems/selenium-webdriver-4.25.0/lib/selenium/webdriver/remote/response.rb:34:in `initialize'
# /usr/local/bundle/gems/selenium-webdriver-4.25.0/lib/selenium/webdriver/remote/http/common.rb:101:in `new'
# /usr/local/bundle/gems/selenium-webdriver-4.25.0/lib/selenium/webdriver/remote/http/common.rb:101:in `create_response'
# /usr/local/bundle/gems/selenium-webdriver-4.25.0/lib/selenium/webdriver/remote/http/default.rb:103:in `request'
# /usr/local/bundle/gems/selenium-webdriver-4.25.0/lib/selenium/webdriver/remote/http/common.rb:67:in `call'
# /usr/local/bundle/gems/selenium-webdriver-4.25.0/lib/selenium/webdriver/remote/bridge.rb:685:in `execute'
# /usr/local/bundle/gems/selenium-webdriver-4.25.0/lib/selenium/webdriver/remote/bridge.rb:119:in `get'
# /usr/local/bundle/gems/selenium-webdriver-4.25.0/lib/selenium/webdriver/common/navigation.rb:32:in `to'
# /usr/local/bundle/gems/capybara-3.40.0/lib/capybara/selenium/driver.rb:95:in `visit'
# /usr/local/bundle/gems/capybara-3.40.0/lib/capybara/session.rb:281:in `visit'
# /usr/local/bundle/gems/capybara-3.40.0/lib/capybara/dsl.rb:52:in `call'
# /usr/local/bundle/gems/capybara-3.40.0/lib/capybara/dsl.rb:52:in `visit'
# ./spec/support/login_macros.rb:3:in `login_as'
# ./spec/system/users_spec.rb:61:in `block (3 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# Selenium::WebDriver::Error::WebDriverError:
# #0 0xaaaab0cf08e8 <unknown>
Capybaraã®èšå®ãè¿œå
Capybara.register_driver :remote_chrome do |app|
options = Selenium::WebDriver::Chrome::Options.new
options.add_argument('no-sandbox')
options.add_argument('headless')
options.add_argument('disable-gpu')
options.add_argument('window-size=1024,768')
options.add_argument('disable-dev-shm-usage') # /dev/shmã®äœ¿çšãç¡å¹ã«ããŠã¡ã¢ãªãçŽæ¥äœ¿çš
options.add_argument('disable-software-rasterizer') # ãœãããŠã§ã¢ã©ã¹ã¿ã©ã€ã¶ãŒãç¡å¹ã«ãã
options.add_argument('disable-extensions') # æ¡åŒµæ©èœãç¡å¹ã«ãã
Capybara::Selenium::Driver.new(app, browser: :remote, url: ENV['SELENIUM_DRIVER_URL'], capabilities: options)
end
åè
1ããŒãžã«2ã€ã®åãèŠçŽ ãããå Žå
1) Users ãã°ã€ã³åŸ ãŠãŒã¶ãŒç·šé ãã©ãŒã ã®å
¥åå€ãæ£åžž ãŠãŒã¶ãŒã®ç·šéãæåãã
Failure/Error: click_link 'ãã°ã€ã³'
Capybara::Ambiguous:
Ambiguous match, found 2 elements matching link "ãã°ã€ã³"
[Screenshot Image]: /myapp/tmp/capybara/failures_r_spec_example_groups_users_nested_2_nested_nested_-_17.png
察å¿ç
çºçããæ¡ä»¶
- åããã¹ããéããŠãæåããæãšå€±æããæããã
- ããã°ã€ã³ããŠãã ãããã®ç»é¢ãã¹ã¯ãªãŒã³ã·ã§ããã§è¡šç€ºãããŠãã
æå
$ docker compose exec web bundle exec rspec spec/system/users_spec.rb
DEPRECATION WARNING: #fog_provider is deprecated and has no effect (called from block in <top (required)> at /myapp/config/initializers/carrierwave.rb:7)
DEPRECATION WARNING: Calling warn on ActiveSupport::Deprecation is deprecated and will be removed from Rails (use your own Deprecation object instead) (called from block in <top (required)> at /myapp/config/initializers/carrierwave.rb:7)
Users
ãã°ã€ã³å
ãŠãŒã¶ãŒã®æ°èŠç»é²
ãã©ãŒã ã®å
¥åå€ãæ£åžž
2024-10-09 15:30:00 INFO Selenium [:logger_info] Details on how to use and modify Selenium logger:
https://selenium.dev/documentation/webdriver/troubleshooting/logging
2024-10-09 15:30:00 WARN Selenium [:clear_session_storage] [DEPRECATION] clear_session_storage is deprecated and will be removed in a future release.
2024-10-09 15:30:00 WARN Selenium [:clear_local_storage] [DEPRECATION] clear_local_storage is deprecated and will be removed in a future release.
ãŠãŒã¶ãŒã®æ°èŠäœæãæåãã
ã¡ãŒã«ã¢ãã¬ã¹ãæªå
¥å
2024-10-09 15:30:00 WARN Selenium [:clear_session_storage] [DEPRECATION] clear_session_storage is deprecated and will be removed in a future release.
2024-10-09 15:30:00 WARN Selenium [:clear_local_storage] [DEPRECATION] clear_local_storage is deprecated and will be removed in a future release.
ãŠãŒã¶ãŒã®æ°èŠäœæã倱æãã
ç»é²æžã¿ã®ã¡ãŒã«ã¢ãã¬ã¹ã䜿çš
2024-10-09 15:30:01 WARN Selenium [:clear_session_storage] [DEPRECATION] clear_session_storage is deprecated and will be removed in a future release.
2024-10-09 15:30:01 WARN Selenium [:clear_local_storage] [DEPRECATION] clear_local_storage is deprecated and will be removed in a future release.
ãŠãŒã¶ãŒã®æ°èŠäœæã倱æãã
ãã€ããŒãž
ãã°ã€ã³ããŠããªãç¶æ
2024-10-09 15:30:01 WARN Selenium [:clear_session_storage] [DEPRECATION] clear_session_storage is deprecated and will be removed in a future release.
2024-10-09 15:30:01 WARN Selenium [:clear_local_storage] [DEPRECATION] clear_local_storage is deprecated and will be removed in a future release.
ãã€ããŒãžã®ã¢ã¯ã»ã¹ã倱æãã
ãã°ã€ã³åŸ
ãŠãŒã¶ãŒç·šé
ãã©ãŒã ã®å
¥åå€ãæ£åžž
WARNING: ignoring the provided expectation message argument({:wait=>5}) since it is not a string or a proc. Called from /myapp/spec/system/users_spec.rb:71:in `block (5 levels) in <top (required)>'.
2024-10-09 15:30:02 WARN Selenium [:clear_session_storage] [DEPRECATION] clear_session_storage is deprecated and will be removed in a future release.
2024-10-09 15:30:02 WARN Selenium [:clear_local_storage] [DEPRECATION] clear_local_storage is deprecated and will be removed in a future release.
ãŠãŒã¶ãŒã®ç·šéãæåãã
Finished in 3.23 seconds (files took 1.76 seconds to load)
5 examples, 0 failures
Coverage report generated for RSpec to /myapp/coverage.
Line Coverage: 23.91% (121 / 506)
倱æ
$ docker compose exec web bundle exec rspec spec/system/users_spec.rb
DEPRECATION WARNING: #fog_provider is deprecated and has no effect (called from block in <top (required)> at /myapp/config/initializers/carrierwave.rb:7)
DEPRECATION WARNING: Calling warn on ActiveSupport::Deprecation is deprecated and will be removed from Rails (use your own Deprecation object instead) (called from block in <top (required)> at /myapp/config/initializers/carrierwave.rb:7)
Users
ãã°ã€ã³å
ãŠãŒã¶ãŒã®æ°èŠç»é²
ãã©ãŒã ã®å
¥åå€ãæ£åžž
2024-10-09 15:30:46 INFO Selenium [:logger_info] Details on how to use and modify Selenium logger:
https://selenium.dev/documentation/webdriver/troubleshooting/logging
2024-10-09 15:30:46 WARN Selenium [:clear_session_storage] [DEPRECATION] clear_session_storage is deprecated and will be removed in a future release.
2024-10-09 15:30:46 WARN Selenium [:clear_local_storage] [DEPRECATION] clear_local_storage is deprecated and will be removed in a future release.
ãŠãŒã¶ãŒã®æ°èŠäœæãæåãã
ã¡ãŒã«ã¢ãã¬ã¹ãæªå
¥å
2024-10-09 15:30:46 WARN Selenium [:clear_session_storage] [DEPRECATION] clear_session_storage is deprecated and will be removed in a future release.
2024-10-09 15:30:46 WARN Selenium [:clear_local_storage] [DEPRECATION] clear_local_storage is deprecated and will be removed in a future release.
ãŠãŒã¶ãŒã®æ°èŠäœæã倱æãã
ç»é²æžã¿ã®ã¡ãŒã«ã¢ãã¬ã¹ã䜿çš
2024-10-09 15:30:47 WARN Selenium [:clear_session_storage] [DEPRECATION] clear_session_storage is deprecated and will be removed in a future release.
2024-10-09 15:30:47 WARN Selenium [:clear_local_storage] [DEPRECATION] clear_local_storage is deprecated and will be removed in a future release.
ãŠãŒã¶ãŒã®æ°èŠäœæã倱æãã
ãã€ããŒãž
ãã°ã€ã³ããŠããªãç¶æ
2024-10-09 15:30:47 WARN Selenium [:clear_session_storage] [DEPRECATION] clear_session_storage is deprecated and will be removed in a future release.
2024-10-09 15:30:47 WARN Selenium [:clear_local_storage] [DEPRECATION] clear_local_storage is deprecated and will be removed in a future release.
ãã€ããŒãžã®ã¢ã¯ã»ã¹ã倱æãã
ãã°ã€ã³åŸ
ãŠãŒã¶ãŒç·šé
ãã©ãŒã ã®å
¥åå€ãæ£åžž
2024-10-09 15:30:50 WARN Selenium [:clear_session_storage] [DEPRECATION] clear_session_storage is deprecated and will be removed in a future release.
2024-10-09 15:30:50 WARN Selenium [:clear_local_storage] [DEPRECATION] clear_local_storage is deprecated and will be removed in a future release.
ãŠãŒã¶ãŒã®ç·šéãæåãã (FAILED - 1)
Failures:
1) Users ãã°ã€ã³åŸ ãŠãŒã¶ãŒç·šé ãã©ãŒã ã®å
¥åå€ãæ£åžž ãŠãŒã¶ãŒã®ç·šéãæåãã
Failure/Error: fill_in 'åå', with: '倪é'
Capybara::ElementNotFound:
Unable to find field "åå" that is not disabled
[Screenshot Image]: /myapp/tmp/capybara/failures_r_spec_example_groups_users_nested_2_nested_nested_-_349.png
# /usr/local/bundle/gems/capybara-3.40.0/lib/capybara/node/finders.rb:312:in `block in synced_resolve'
# /usr/local/bundle/gems/capybara-3.40.0/lib/capybara/node/base.rb:84:in `synchronize'
# /usr/local/bundle/gems/capybara-3.40.0/lib/capybara/node/finders.rb:301:in `synced_resolve'
# /usr/local/bundle/gems/capybara-3.40.0/lib/capybara/node/finders.rb:60:in `find'
# /usr/local/bundle/gems/capybara-3.40.0/lib/capybara/node/actions.rb:91:in `fill_in'
# /usr/local/bundle/gems/capybara-3.40.0/lib/capybara/session.rb:774:in `fill_in'
# /usr/local/bundle/gems/capybara-3.40.0/lib/capybara/dsl.rb:52:in `call'
# /usr/local/bundle/gems/capybara-3.40.0/lib/capybara/dsl.rb:52:in `fill_in'
# ./spec/system/users_spec.rb:67:in `block (5 levels) in <top (required)>'
Finished in 4.94 seconds (files took 1.79 seconds to load)
5 examples, 1 failure
Failed examples:
rspec ./spec/system/users_spec.rb:65 # Users ãã°ã€ã³åŸ ãŠãŒã¶ãŒç·šé ãã©ãŒã ã®å
¥åå€ãæ£åžž ãŠãŒã¶ãŒã®ç·šéãæåãã
Coverage report generated for RSpec to /myapp/coverage.
Line Coverage: 22.13% (112 / 506)
Stopped processing SimpleCov as a previous error not related to SimpleCov has been detected
ãã°ã€ã³ã¢ãžã¥ãŒã«ã«ãªãã€ã¬ã¯ãè¿œå
ã³ã³ãœãŒã«ã§ãã¹ã確èª
userãšother_userãèšå®
[1] pry(main)> user = User.first
User Load (1.3ms) SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> #<User:0x00
id: 1,
email: "koko0@email",
crypted_password: "xxxxxxxxx",
salt: "xxxxxx",
name: "倪é0",
created_at: Thu, 18 Jul 2024 17:12:56.589333000 JST +09:00,
updated_at: Thu, 18 Jul 2024 17:12:56.589333000 JST +09:00,
reset_password_token: nil,
reset_password_token_expires_at: nil,
reset_password_email_sent_at: nil,
access_count_to_reset_password_page: 0,
avatar: nil,
gender: nil,
age: nil>
[2] pry(main)> other_user = User.last
User Load (3.6ms) SELECT `users`.* FROM `users` ORDER BY `users`.`id` DESC LIMIT 1
=> #<User:0x00
id: 29,
email: "rant@pom",
crypted_password: "xxxxxxxxx",
salt: "xxxxxx",
name: "koko",
created_at: Sun, 15 Sep 2024 13:49:41.149525000 JST +09:00,
updated_at: Sun, 15 Sep 2024 13:49:52.392101000 JST +09:00,
reset_password_token: nil,
reset_password_token_expires_at: nil,
reset_password_email_sent_at: nil,
access_count_to_reset_password_page: 0,
avatar: nil,
gender: nil,
age: "teens">
ãã¹ã®ç¢ºèª
[9] pry(main)> app.edit_mypage_profiles_path(user)
=> "/mypage/profiles/edit.1"
[10] pry(main)> app.edit_mypage_profiles_path(other_user)
=> "/mypage/profiles/edit.29"
åè
TDDã¯æ»ãã ããã¹ãã£ã³ã°ãæ ãã
ã¢ã€ã³ã³ãã¿ããããã·ã¹ãã ã¹ããã¯
- ãæ°ã«å ¥ãæ©èœã¯ã¢ã€ã³ã³ãã¿ããããããšã«ãã£ãŠç»é²ããã
åè
ãæ°ã«å ¥ãããã®ãã€ããŒãž
ããããããš
- æçš¿ãäœæ
- ãã®æçš¿ããæ°ã«å ¥ã
- èªåã®ãæ°ã«å ¥ãäžèŠ§ã§è¡šç€º
æžããã³ãŒã
context 'æçš¿ããæ°ã«å
¥ã' do
it 'ãæ°ã«å
¥ãããæçš¿ã衚瀺ããã' do
create(:post, restaurant_name: 'ã¬ã¹ãã©ã³ãæ°ã«', body: 'ãšãŠããããããª', user: user )
visit post_path(post)
link = find('#bookmark-button-for-post-#{post.id}') #äœæããæçš¿ã®ãæ°ã«å
¥ããã¿ã³ãæå®ãããã£ã
link.click
visit mypage_bookmark_posts_path
expect(page).to have_content('ã¬ã¹ãã©ã³ãæ°ã«')
expect(page).to have_content('ãšãŠããããããª')
end
end
倱æâ
Failures:
1) Users ãã°ã€ã³åŸ ãã€ããŒãž æçš¿ããæ°ã«å
¥ã ãæ°ã«å
¥ãããæçš¿ã衚瀺ããã
Failure/Error: visit post_path(post)
ArgumentError:
wrong number of arguments (given 0, expected 1)
[Screenshot Image]: /myapp/tmp/capybara/failures_r_spec_example_groups_users_nested_2_nested_2_nested_2_-_342.png
# ./spec/system/users_spec.rb:102:in `block (5 levels) in <top (required)>'
Finished in 6 seconds (files took 1.84 seconds to load)
- postã®åŒæ°ããªãã§ãããã
-
post = create(:post, restaurant_name: 'ã¬ã¹ãã©ã³ãæ°ã«', body: 'ãšãŠããããããª', user: user )
ã§è§£æ±º
倱æ
1) Users ãã°ã€ã³åŸ ãã€ããŒãž æçš¿ããæ°ã«å
¥ã ãæ°ã«å
¥ãããæçš¿ã衚瀺ããã
Failure/Error: link = find('#bookmark-button-for-post-#{post.id}')
Selenium::WebDriver::Error::InvalidSelectorError:
invalid selector: An invalid or illegal selector was specified
(Session info: chrome-headless-shell=121.0.6167.85); For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#invalid-selector-exception
-
link = find("#bookmark-button-for-post-#{post.id}")
åŒå±éãããªãããã«ã¯ã©ãŒãŠã·ã§ã³ã§ããããšChatGPTã«åç¬ãã§ææãããïŒè¢«å®³åŠæ³ïŒ
äžæŠå®æ
context 'æçš¿ããæ°ã«å
¥ã' do
it 'ãæ°ã«å
¥ãããæçš¿ã衚瀺ããã' do
post = create(:post, restaurant_name: 'ã¬ã¹ãã©ã³ãæ°ã«', body: 'ãšãŠããããããª', user: user )
visit post_path(post)
link = find("#bookmark-button-for-post-#{post.id}")
link.click
visit current_path
visit mypage_bookmark_posts_path
expect(page).to have_content('ã¬ã¹ãã©ã³ãæ°ã«')
expect(page).to have_content('ãšãŠããããããª')
end
end
- Turboç³»ã®ãšããããªããŒãããªããšããŸããããªãã®ãªãã ãããªã
ãã°ã¢ãŠããã¹ã
- ãã°ã¢ãŠãã®æã data-confirmåºãŠããŠOKããªãããã°ã¢ãŠãã§ããªã
it 'ãã°ã¢ãŠãåŠçãæåãã' do
click_link 'ãã°ã¢ãŠã', match: :first # ãã°ã¢ãŠãã£ãŠååã®ãªã³ã¯2ã€ããã®ã§çæ¹ã«æå®
# ãã°ã¢ãŠããæåããããšã確èªãããã¹ã
page.accept_alert 'ãã°ã¢ãŠãããŠãããããã§ããïŒ'
expect(page).to have_content 'ãã°ã€ã³'
end
end
accept_alert
ã£ãŠãªãã ãã
- READMEã«ãæžããŠãã
- è²ã
ããã³ãã£ãœãäœæ¥ã§ããããšã¯äžèšã«ãããã
https://github.com/teamcapybara/capybara/blob/0480f90168a40780d1398c75031a255c1819dce8/lib/capybara/session.rb#L659
䜿ããRSpecå ¥éã»ãã®1ãRSpecã®åºæ¬çãªæ§æã䟿å©ãªæ©èœãç解ããã #Ruby - Qiita
- 1ã€ã®exampleã«è€æ°ã®ãšã¯ã¹ãã¯ããŒã·ã§ã³ã眮ããšã©ãã§ãã¹ãã«èœã¡ãŠããã®ãåãããªãã®ã§ãããæ¹ãè¯ã
- describe ã¯ããã€ã§ãæžãããããã¹ããããããšãã§ãã
- äžçªå€åŽã®describe以å€ã¯RSpecãçç¥ã§ããã
- before do ... end ã§å²ãŸããéšå㯠example ã®å®è¡åã«æ¯ååŒã°ãã=å
±éã®æºåããããšãã¯ããã§æžããšåãããããïŒãããã¯ãªã®ã§
before { login_as(user) }
ãšæžããéšåãåãã§ããªïŒ -
let
ã®ã¡ãªããã¯é 延è©äŸ¡ïŒé¢é£èšäºåèïŒ - subjectãšãããã®ããã£ãŠãŸãšããŠæžããããããŸã䜿ããªãïŒïŒåãRSpecã§subjectã䜿ããªãçç± - give IT a tryïŒ
- æå·§çãªãã¹ãã³ãŒãã¯é¿ããŸãããããã¹ãã³ãŒãã¯DRYããããèªã¿ããããéèŠããŸãããã
-
context
ãit
ã®ããšã¯æ¥æ¬äººããèªãŸãªããªãæ¥æ¬èªã§è¯ã - it/example/specifyã¯ãšã€ãªã¢ã¹
-
shared_examples
ãšit_behaves_like
ãšããæ©èœã䜿ããšãexample ãåå©çšããããšãã§ãã -
shared_context
ãšinclude_context
ã䜿ããšã context ãåå©çšããããšãã§ãã -
let
ã®é 延è©äŸ¡ãåå ã§ãã¹ãã«èœã¡ãéã¯ãlet!
ã䜿çšãã -
pending
ïŒå®è¡ãç¶ããŠä¿çãã=ç¥ããéã«ãã¹ãéãããã«ãªã£ãŠãçŸè±¡ãæ¶ãã -
skip
ïŒåçç¡çšã§ãã¹ããæ¢ãã -
xit
ïŒexampleäžžããšã¹ããã -
xdescribe
/xcontext
ïŒã°ã«ãŒãäžžããšã¹ããã
RSpecã®letã䜿ãã®ã¯ã©ããªãšããïŒïŒç¿»èš³ïŒ #Ruby - Qiita
é¢é£èšäºïŒ- letã¯ã¡ãœãããäœãã®ã§typoãããšNameErrorãçºçããïŒïŒïŒ
- ç¡é§ãªåæåã®æéãæžããã
- ããŒã«ã«å€æ°ããã®ãŸãŸletã«çœ®ãæãããã
- åçŽã«èªã¿ããã
- é 延åæåãããã®ã§ãã¹ããã¯ãã®ãã¹ãããã¹ããªãæ¡ä»¶ãçºçãã
ããŒããã©ãªãªãã¹ãåè
å°å³é¢é£
ãªã¬ãŒã·ã§ã³é¢é£
䜿ããRSpecå ¥éã»ãã®2ã䜿çšé »åºŠã®é«ããããã£ã䜿ãããªãã #Ruby - Qiita
- ãããã£ïŒnotðµïŒïŒæåŸ
å€ãšå®éã®å€ãæ¯èŒããŠãäžèŽããïŒãããã¯äžèŽããªãã£ãïŒãšããçµæãè¿ããªããžã§ã¯ããexpect(...).to xxx ã®
to
ã®çŽåŸã«åºãŠãããã€ããããã£ãªã®ã§to
èªäœã¯ãããã£ã§ã¯ãªãã§ã -
not_to
ãšto_not
ïŒã©ã£ã¡ã§ããããã©ãšããããããã¥ã¡ã³ãã§ããåºãŠããnot_to
ã䜿ãã®ã¯ãããã§ãããïŒ -
expect(A).to be B
ïŒA.equal?(B)ãããªãã¡åäžã€ã³ã¹ã¿ã³ã¹ã§ããã°ãã¹ãã -
expect(A).to eq B
ïŒA == Bãããªãã¡åå€ã§ããã°ãã¹ããïŒãã£ã¡äœ¿ã£ãŠãããªãeq login_path
ãbeã«çœ®ãæããããã¹ãèœã¡ããã ãããïŒïŒ - empty? ã®ããã«ã¡ãœããåãã?ãã§æ»ãå€ãbooleanã«ãªãã¡ãœãããbe_emptyã®ãããªåœ¢ã§æ€èšŒã§ãã
- RSpecã§çåœå€ã確èªãããã¹ããæžãå Žåã¯ç¹å¥ãªäºæ
ããªãéãã
be_truthy
/`be_falseãšæžãã®ããããã - changeã¯äœãã®å€ãå€ããéã®èšè¿°ãã§ãããç¹ã«ãªã¬ãŒã·ã§ã³é¢ä¿ã§èšè¿°ãããéã«äŸ¿å©ïŒåèïŒ
- includeïŒé åã«å«ãŸããŠããããš
- raise_errorïŒãšã©ãŒãèµ·ããããš
- be_within + ofïŒæºãããããéã®æ¯ãå¹ ãèšå®ã§ãã
to be
ãšto eq
ã®éããè©ŠããŠã¿ã
ã³ãŒã
### å®éš
```ruby
describe 'ãã°ã€ã³åŸ' do
context 'ãã°ã¢ãŠããã¿ã³ãã¯ãªãã¯' do
it 'ãã°ã¢ãŠãåŠçãæåãã' do
login_as(user)
click_link 'ãã°ã¢ãŠã', match: :first
# ãã°ã¢ãŠããæåããããšã確èªãããã¹ã
page.accept_alert 'ãã°ã¢ãŠãããŠãããããã§ããïŒ'
expect(page).to have_content 'ãã°ã€ã³'
visit current_path
expect(current_path).to be root_path #eqããbeã«å€æŽãeqã®æã¯ãã¹ããã¹ããŠãŸãã
end
end
end
å®è¡çµæ
ãã°ã¢ãŠãåŠçãæåãã (FAILED - 1)
Failures:
1) UserSessions ãã°ã€ã³åŸ ãã°ã¢ãŠããã¿ã³ãã¯ãªã㯠ãã°ã¢ãŠãåŠçãæåãã
Failure/Error: expect(current_path).to be root_path
expected #<String:32860> => "/"
got #<String:32880> => "/"
Compared using equal?, which compares object identity,
but expected and actual are not the same object. Use
`expect(actual).to eq(expected)` if you don't care about
object identity in this example.
[Screenshot Image]: /myapp/tmp/capybara/failures_r_spec_example_groups_user_sessions_nested_2_nested_-_822.png
# ./spec/system/user_sessions_spec.rb:39:in `block (4 levels) in <top (required)>'
- ïŒïŒã€ã³ã¹ã¿ã³ã¹ãéããŸãããã£ãŠå€±æããïŒé¢çœãïŒïŒ
- ã¡ãããšæžãæãã®ææ¡ãŸã§ããŠãã ããã®ã...
GitHub Actionsã®ã¹ããŒãã¢ãã
- æ°ã«ãªãð
- ãã£ãã·ã¥ã®äœ¿çšã¯ãã£ãŠã¿ãã
- å°å ¥åœåããããããã倱æç¶ãã§ãã£ãã·ã¥ã®åé€ããŠãæ°ããããã
create_list
ã«ã€ããŠ
- FactoryBotã§è€æ°ã®ããŒã¿äœããããªã£ãŠæã«äœ¿ã
- å®çŸ©å Žææ¢ãããšæã£ããã©ã©ãããã¡ã¿ãã䜿ã£ãŠãããããã®ã§æ念
PBT
- å ¥åå€ã®ããããã£ãŒãæå®ããããšã«ãã£ãŠãã¹ããæžããããã
- å ¥åå€ã«å ·äœçãªå€ã§ã¯ãªããæŽæ°ã®ãããªæ§è³ªãæå®ããŠ100åãã¹ãããŠããã
䜿ããRSpecå ¥éã»ãã®4ãã©ããªãã©ãŠã¶æäœãèªç±èªåšïŒéåŒãCapybara倧èŸå žã #Ruby - Qiita
- å¿ èŠã«å¿ããŠèªã¿è¿ããŸãããèšäº
- HTMLäžã§aèŠçŽ ã§ããã°ãã¿ã³ã§ã¯ãªããªã³ã¯ã«ãªãã®ã§
click_link 'New User'
ã«ãªã - ãã¿ã³ããªã³ã¯ãåãããªãå Žåã¯ã
click_on 'New User'
ãäŸ¿å© - ç»åã®altå±æ§ïŒ
click_link
ãclick_on
- ãã¡ã€ã«ãæ·»ä»ããïŒ
attach_file
- hiddenã«å€ãã»ããããïŒfindã䜿ããšç»é¢äžã«ããèŠçŽ ããæ€çŽ¢ããªãã®ã§ã
visible: false
ãªãã·ã§ã³ãã€ãããå°å³ã®æ€çŽ¢ã®æã«äœ¿ãããã - ã©ãã«ããªããã£ãŒã«ããæäœå¯èœ=>ã©ãã«ããã¯ããªã®ã«æå®ã§ããªããªãã£ãŠæã¯HTMLã確èªããŸããã
- ç¹å®ã®ã¿ã°ãCSSèŠçŽ ã«ç¹å®ã®æååã衚瀺ãããŠãããæ€èšŒïŒéèŠãªãç¥ããã衚瀺ãããŠãã確èªã§ããã®ããã
- ããŒãžå ã«ç¹å®ã®ãªã³ã¯ã»ãã¿ã³ããããããã§ãã¯ããã¯ã¹ã«ãã§ãã¯ããããŠãããã®ããã«ãçŸç¶ã®æ€èšŒãè¡ãå Žåãããã
- ã¬ã¹ãã³ã¹ã®ã¹ããŒã¿ã¹ã³ãŒããæ€èšŒããïŒAPIã«ãªãã¥ã©ã ã§åºãŠããŠãããª
expect(response).to have_http_status(:ok)
æååã§æå®ã§ããªãå Žå
- classãæå®ïŒ
'.settings-link'
ïŒ - idã§æå®ïŒ
'#settings-link'
ïŒ
è€æ°ã®èŠçŽ ã®çµã蟌ã¿
- withinã§ã¹ã³ãŒããçµã
within '.section-drug' do
choose 'ã¯ã'
end
within '.section-disease' do
choose 'ããã'
end
- ãã倧äºã ãªãã¯ã©ã¹ã§ãŸãšããŠãªããšãã¹ãæžããªãã®ãªã
- ããã¹ããã«ããviewã¯ãã¹ããããããããã«å€æŽããããšããã確ãã«ã
ãã®ä»
-
save_and_open_page
ã§ãã¹ã倱æããå Žåã®ç»é¢ãéã - JSã®ãã¹ãïŒ
js: true
ã«ããããJavaScriptãå®è¡ããå Žåã¯ãPoltergeistã®ãããªJavaScriptãã©ã€ãã®èšå®ãå¿ èŠã«ãªããŸããããšããã®ã§èšå®ãå¿ èŠããïŒ - JSã®ãã¹ããåå äžæã§èœã¡ãããšãããïŒrspec-retryãšããgemã䜿ããšããããã