ruby on rails - Capybara and JavaScript: checking for visibility requires huge amounts of time! How to optimise? -
while creating javascript functionality in rails, use ugly capybara specs me assuring works. 1 of these specs looks this:
it 'creates report document', js: true visit new_project_report_document_path @project expect(page).to have_active_navigation_items 'projects' expect(page).to have_breadcrumbs 'a4aa 2.0', 'projects', 'project test name', 'reports', 'create' expect(page).to have_headline 'create report' expect { select 'template 1', from: 'report_report_template_id' }.to change { page.has_css? "[data-template-inputs-id='#{@report_template_1.id}']", visible: true }.from(false) .and change { page.has_css? "[data-template-inputs-id='#{@report_template_1.id}'] #report_name[disabled]", visible: false}.from(true) .and change { page.has_css? "[data-template-inputs-id='#{@report_template_1.id}'] #report_description[disabled]", visible: false}.from(true) .and change { page.has_css? "[data-template-inputs-id='#{@report_template_1.id}'] #report_intro[disabled]", visible: false}.from(true) .and change { page.has_css? "[data-template-inputs-id='#{@report_template_1.id}'] #report_content[disabled]", visible: false}.from(true) .and change { page.has_css? "[data-template-inputs-id='#{@report_template_1.id}'] #report_outro[disabled]", visible: false}.from(true) expect(page).to have_css "[data-template-inputs-id='#{@report_template_1.id}'] #report_name", text: @report_template_1.name expect(page).to have_css "[data-template-inputs-id='#{@report_template_1.id}'] #report_description", text: '' expect(page).to have_css "[data-template-inputs-id='#{@report_template_1.id}'] #report_intro", text: @report_template_1.intro expect(page).to have_css "[data-template-inputs-id='#{@report_template_1.id}'] #report_content", text: @report_template_1.content expect(page).to have_css "[data-template-inputs-id='#{@report_template_1.id}'] #report_outro", text: @report_template_1.outro expect { select 'template 2', from: 'report_report_template_id' }.to change { page.has_css? "[data-template-inputs-id='#{@report_template_1.id}']", visible: true }.from(true) .and change { page.has_css? "[data-template-inputs-id='#{@report_template_1.id}'] #report_name[disabled]", visible: false}.from(false) .and change { page.has_css? "[data-template-inputs-id='#{@report_template_1.id}'] #report_description[disabled]", visible: false}.from(false) .and change { page.has_css? "[data-template-inputs-id='#{@report_template_1.id}'] #report_intro[disabled]", visible: false}.from(false) .and change { page.has_css? "[data-template-inputs-id='#{@report_template_1.id}'] #report_content[disabled]", visible: false}.from(false) .and change { page.has_css? "[data-template-inputs-id='#{@report_template_1.id}'] #report_outro[disabled]", visible: false}.from(false) .and change { page.has_css? "[data-template-inputs-id='#{@report_template_2.id}']", visible: true }.from(false) .and change { page.has_css? "[data-template-inputs-id='#{@report_template_2.id}'] #report_name[disabled]", visible: false}.from(true) .and change { page.has_css? "[data-template-inputs-id='#{@report_template_2.id}'] #report_description[disabled]", visible: false}.from(true) .and change { page.has_css? "[data-template-inputs-id='#{@report_template_2.id}'] #report_intro[disabled]", visible: false}.from(true) .and change { page.has_css? "[data-template-inputs-id='#{@report_template_2.id}'] #report_content[disabled]", visible: false}.from(true) .and change { page.has_css? "[data-template-inputs-id='#{@report_template_2.id}'] #report_outro[disabled]", visible: false}.from(true) expect(page).to have_css "[data-template-inputs-id='#{@report_template_2.id}'] #report_name", text: @report_template_2.name expect(page).to have_css "[data-template-inputs-id='#{@report_template_2.id}'] #report_description", text: '' expect(page).to have_css "[data-template-inputs-id='#{@report_template_2.id}'] #report_intro", text: @report_template_2.intro expect(page).to have_css "[data-template-inputs-id='#{@report_template_2.id}'] #report_content", text: @report_template_2.content expect(page).to have_css "[data-template-inputs-id='#{@report_template_2.id}'] #report_outro", text: @report_template_2.outro fill_in 'report_name', with: 'newname' fill_in 'report_description', with: 'newdescription' fill_in 'report_intro', with: 'newintro' fill_in 'report_content', with: 'newcontent' fill_in 'report_outro', with: 'newoutro' click_button 'create report' expect(page).to have_flash 'report created.' end
i know it's ugly spec, noticed takes huge amount of time: 40secs!
finished in 41.86 seconds (files took 0.44731 seconds load)
here's spec has javascript activated. although it's smaller (and 1 full page load happens), think time needs improportionally less 1 above:
it 'allows remove existing finding', js: true, focus: true visit edit_project_boilerplate_copy_path(@boilerplate_copy.project, @boilerplate_copy) click_link 'remove finding' expect { click_button 'update boilerplate' } .to change { finding.count }.by -1 end
it takes 6-7secs:
finished in 6.62 seconds (files took 0.52104 seconds load)
so wonder why first 1 needs time. full spec suite around 400 specs , took around minute, adding new spec increases 2 minutes! isn't acceptable.
so: how can js spec improved? have many visible: false
statements? or many and change { ... }
stuff? maybe both in interaction?
when removing lines have visible: false
in them, goes faster:
finished in 6.39 seconds (files took 0.41315 seconds load)
i use capybara (2.5.0), rspec (3.3.0), rails (4.2.1), , poltergeist (1.7.0) phantomjs (1.9.8) on osx el capitan.
your test slow becauase you're running capybaras waiting behavior. #has_css?/have_css
wait capybara.default_max_wait_time seconds matching elements appear on page before responding false if don't. when expect element not on page want using #has_no_css?/have_no_css (or not_to #has_css?/have_css since end being same thing) since return element not found.
has_css?(....) #will wait until element appears or default_max_wait_time has_no_css?(....) #will wait until element gone or default_max_wait_time
basically in case, don't want using change
matcher has_css? because doesn't allow use method match possible on each side of action. if want keep change
matcher potential option pass small wait value has_css? wait: 0.5
or decrease max wait time item, may need tweaked allow whatever actions occur on page complete
Comments
Post a Comment