Formal testing with respect to user needs, requirements, and business processes conducted to determine whether or not a system satisfies the acceptance criteria and to enable the user, customers or other authorized entity to determine whether or not to accept the system.
-- International Software Testing Qualifications Board
A test that must pass for the user story you're working on to be complete -- Jason Carter
The name acceptance tests was changed from functional tests. This better reflects the intent, which is to guarantee that a customers requirements have been met and the system is acceptable.
-- Don Wells, extremeprogramming.org
- Write the acceptance test to know when the feature is done
- Test drive the implementation with unit and integration specs
- Refactor safely knowing that the feature still works the way it should
- General principles
- Avoiding "intermittent failures"
- Vanilla
- Setup, Actions, and Assertions
- Page Object pattern
- Random musings
describe 'when deleting an existing Review', js: true, type: :request do
# A bunch of lets
context 'When the user is a review creator' do
it 'can be deleted' do
find('.workspace-proof-title', text: proof.title).click
within '.workspace-proofs-table' do
within 'tr', text: 'some proof' do
expect(page).to have_text('In Review ( 1/2 )')
end
end
within '#side-panel' do
find('span', text: 'Delete Review').click
end
within '.show-mavenlink-alert' do
expect(page).to have_selector('h2', text: 'Delete')
expect(page).to have_selector('button', text: 'Delete')
expect(page).to have_selector('button', text: 'Cancel')
click_button('Delete')
end
within '#side-panel' do
expect(page).to have_button('Create Review')
end
find('.js-panel-close-link').click
find('.workspace-proof-title', text: 'Some Proof').click
within '#side-panel' do
expect(page).to have_button('Create Review')
end
within '.workspace-proofs-table' do
within 'tr', text: proof.title do
expect(page).to have_no_text('In Review ( 1/2 )')
end
end
end
end
end
end
describe 'when deleting an existing Review', js: true, type: :request do
# a bunch of lets
it 'can be deleted' do
navigate_to_proof_tab(proof_employee, workspace)
click_proof_title(proof)
it_should_have_proof_with_status(proof, 'In Review ( 1/2 )')
click_delete_review
confirm_action 'Delete'
it_has_create_review_option
it_persists_the_delete(proof)
it_should_not_have_proof_with_status(proof, 'In Review ( 1/2 )')
end
end
describe 'inviting people to a workspace', js: true, type: :request do
describe 'the invitation flow' do
context 'when adding to consultants' do
context 'when the account is not free or trialing' do
let(:project_invitation_form) { Pages::ProjectInvitations::Form.new('maven') }
let(:inviting_user) { users(:jane) }
let(:invited_user) { users(:alice) }
let(:workspace) { workspaces(:jane_car_wash) }
it 'will invite a maven to a workspace' do
login(inviting_user)
visit workspace_path(workspace)
invite_a(team, invited_user)
expect(project_invitation_form).to have_save_message_as_default_checkbox
expect(project_invitation_form).to have_no_subject_and_message_tipsy
expect(project_invitation_form).to have_no_upgrade_call_to_action
expect(project_invitation_form.send_invitation).to have_sent_an_invitation
end
end
end
end
end
module Pages
module ProjectInvitations
class Form
include Capybara::DSL
def initialize(team)
@team = team
end
def has_save_message_as_default_checkbox?
page.has_css?('#save_message_as_default')
end
def send_invitation
click_button 'Send invitation'
self
end
def has_sent_an_invitation?
within('.flash-container') do
page.has_css?('.notice', text: '1 invitation was sent for this project')
end
end
def has_not_sent_an_invitation?
within('.flash-container') do
page.has_css?('.notice', text: 'The invited user must be a member of your account.')
end
end
end
end
end
def has_sent_an_invitation?
within('.flash-container') do
page.has_css?('.notice', text: '1 invitation was sent for this project')
end
end
# Selenium does some magic for us
# has_sent_invitation? -> have_sent_an_invitation
Returning self
lets us chain things together, and use the to
syntax
def send_invitation
click_button 'Send invitation'
self
end
describe 'inviting people to a workspace', js: true, type: :request do
describe 'the invitation flow' do
context 'when adding to consultants' do
context 'when the account is not free or trialing' do
# ...
expect(project_invitation_form.send_invitation).to have_sent_an_invitation
end
end
end
end
end
Martin Fowler said its awesome!
expect(project_invitation_form.send_invitation).to [
have_sent_an_invitation,
have_notified_some_service,
have_done_something_else
]
def run_conceptshare_jobs_immediately
stub(Delayed::Job).enqueue do |job|
job.perform if job.respond_to?(:queue_name) && job.queue_name == 'conceptshare'
true
end
end
context 'when adding to a workspace mapped to conceptshare' do
it 'will create a conceptshare mapping for the participation' do
run_conceptshare_jobs_immediately
mock.any_instance_of(Conceptshare::AccountClient).create_user_if_necessary(invited_user)
mock.any_instance_of(Conceptshare::AccountClient).add_user_to_account(invited_user)
mock.any_instance_of(Conceptshare::AccountClient).add_user_to_project(invited_user, workspace, "Commentator")
login(inviting_user)
visit workspace_path(workspace)
invite_a(team, invited_user)
project_invitation_form.send_invitation
end
end