SlideShare a Scribd company logo
1 of 37
Download to read offline
• Alex Chaffee
• Brian Takita
Full-stack webapp testing with Selenium and Rails
• Want to test your entire Web 2.0 app, from AJAX and DHTML through browser-rendered
HTML into a live instance of your application and database? Most web testing frameworks
have gaps in their coverage: JUnit and Test::Unit miss the client frontend; JSUnit misses the
server backend; web testing frameworks miss some or all of the JavaScript. With Selenium
we have a framework that can test the whole application, from browser-executed JavaScript,
through a live application backend, then back to assertions on browser-rendered DOM code.
Selenium RC takes this further: since you write your tests in your application language, your
tests can do data setup and assertions based directly on server-side domain objects that
may be inaccessible or only partially accessible from the client side. On our teams we have
used and developed a series of helper methods and assertions that allow testing of AJAX
and DHTML functions as well.
In this tutorial we outline the architecture of Selenium RC and walk through code and
examples illustrating how to do full-stack testing against a Ruby on Rails application.
Abstract
• Selenium runs in the browser
• Executes your app in a frame
• Simulates user actions via JavaScript
• Goes all the way to the server and back
• Complementary to JSUnit
• JSUnit tests JS pages only, not interaction with server
• Fun to watch
Selenium Features
• Basic example (login_test.rb)
• def test_login
open "/"
assert_text_present("Please sign in")
type "username", "jdoe"
type "password", "password"
click "submit"
assert_text_present("Welcome, John Doe")
open "/"
assert_text_present("Welcome, John Doe")
end
• Sort of a DSL ("Selenese")
• Written in Ruby
• Can also use Java, .NET, Python, Perl, etc.
First Example
• Can access database and/or domain objects
• def test_signup
open "/signup"
assert_text_present("Please sign up")
type "username", "noob"
type "fullname", "New Bie"
type "password", "secret"
type "password_verify", "secret"
click "submit"
assert_text_present("Welcome, New Bie")
user = User.find_by_username("noob")
assert user.authenticate("secret")
end
Accessing Your World
• def test_signup_via_email
open "/signup"
assert_text_present("Please sign up")
type "email", "noob@example.com"
click "submit"
assert_text_present("An email has been sent to noob@example.com")
wait_for { !ActionMailer::Base.deliveries.empty? }
user = User.find_by_email("noob@example.com”)
assert !user.verified?
link = extract_link(ActionMailer::Base.deliveries[0].body)
open link
wait_for do
user.reload
user.verified?
end
end
def extract_link(s)
/http://S*/.match(s)[0]
end
Or even email!
• def test_signup_via_email
open "/signup"
assert_text_present("Please sign up")
type "email", "noob@example.com"
click "submit"
assert_text_present("An email has been sent to noob@example.com")
wait_for { !ActionMailer::Base.deliveries.empty? }
user = User.find_by_email("noob@example.com”)
assert !user.verified?
link = extract_link(ActionMailer::Base.deliveries[0].body)
open link
wait_for do
user.reload
user.verified?
end
end
def extract_link(s)
/http://S*/.match(s)[0]
end
Or even email!
• def test_signup_via_email
open "/signup"
assert_text_present("Please sign up")
type "email", "noob@example.com"
click "submit"
assert_text_present("An email has been sent to noob@example.com")
wait_for { !ActionMailer::Base.deliveries.empty? }
user = User.find_by_email("noob@example.com”)
assert !user.verified?
link = extract_link(ActionMailer::Base.deliveries[0].body)
open link
wait_for do
user.reload
user.verified?
end
end
def extract_link(s)
/http://S*/.match(s)[0]
end
Or even email!
• def test_signup_via_email
open "/signup"
assert_text_present("Please sign up")
type "email", "noob@example.com"
click "submit"
assert_text_present("An email has been sent to noob@example.com")
wait_for { !ActionMailer::Base.deliveries.empty? }
user = User.find_by_email("noob@example.com”)
assert !user.verified?
link = extract_link(ActionMailer::Base.deliveries[0].body)
open link
wait_for do
user.reload
user.verified?
end
end
def extract_link(s)
/http://S*/.match(s)[0]
end
Or even email!
• def test_signup_via_email
open "/signup"
assert_text_present("Please sign up")
type "email", "noob@example.com"
click "submit"
assert_text_present("An email has been sent to noob@example.com")
wait_for { !ActionMailer::Base.deliveries.empty? }
user = User.find_by_email("noob@example.com”)
assert !user.verified?
link = extract_link(ActionMailer::Base.deliveries[0].body)
open link
wait_for do
user.reload
user.verified?
end
end
def extract_link(s)
/http://S*/.match(s)[0]
end
Or even email!
And don’t forget to extract a DSL
def login(user_name,password)
open('/login')
type "id=login", user_name
type "id=password", password
click_and_wait "commit"
end
def logout
open('/logout')
end
Remote (possibly)
Selenium Test Suite
Webrick running app
(in "test" mode)
Selenium Server Browser
DOM/JS
Launch
Browser
rake selenium:server
rake selenium:test
Launch
Launch
Database
Launch
Browser
Selenium RC Architecture: launch
Remote (possibly)
Selenium Test Suite
Webrick running app
(in "test" mode)
def test_foo
click "submit"
end
Selenium Server Browser
Selenese
Interpreter
DOM/JS
click
'submit'
click
'submit'
Proxy
HTTP
HTTP
rake selenium:server
rake selenium:test
Launch
Launch
Database
Selenium RC Architecture: run test
• OS (Unix, Windows, Mac)
• Browser (IE, Firefox, Safari)
• The Selenium Farm (Continuous Integration)
Multiple Platform Support
• Web 2.0 is Asynchronous and Dynamic
• The “A” in "AJAX"
• The "D" in "DHTML"
• The problem:
• Since they happen unpredicatably, and inside the context of a single page,
they’re harder to test
Good Things Come To Those Who Wait
• wait_for function
• executes in Ruby
• wait_for_condition action
• takes a JavaScript expression, evals it in browser
• wait_for_condition is complementary to wait_for
• JavaScript can't poll DB or domain objects
• Write your conditions in the language you prefer
Good Things Come To Those Who Wait
• Tracker
• project_page_editing_test
• Peer2Patent
• create_prior_art_test
• registration_mode_test
More examples
• Integration Tests
• Test multiple layers of your app working together
• Acceptance Tests
• Test specific customer features and/or scenarios
• UI tests
• Test complicated or detailed UI widgets
• Smoke Tests
• Special case of Integration Tests
• Make sure your app doesn’t blow up
What kind of tests?
• Selenium tests are integration tests in the abstract
• Not derived from Rails Integration Tests
• Rails ITs are faster
• Selenium tests are better for testing AJAX, DHTML, widgets, full-stack
integration
• Where you can do a test in Ruby instead of Selenium... you should.
Wait, do you mean Integration Tests or
Integration Tests?
• Test full stack
• Test JS->server interaction
• Test emails
• Smoke testing
• Testing in multiple browsers
When to use Selenium?
Particular Strengths of Selenium Tests
• AJAX/RJS tests
• Test what state the browser is in after the RJS/AJAX call
• JS tests
• Test JavaScript interacting with your DOM
• Not just functional/behavioral JS (which JSUnit is great for)
• For every edge case
• Want to test happy path, and one or two error paths
• When speed is of the essence
• e.g. in a suite you run a lot, or when your tests start taking more than a few minutes
• see next slide...
• When you’re testing fine-grained features
• Selenium tests tend to sprawl out
• setup/teardown are more expensive, so you want to test more things per test
• Unit tests should be small and isolated
When not to use Selenium?
• Selenium is much faster than a human, but still much slower than unit tests.
How do we deal with that?
• Fast Suite / Slow Suite
• Run Fast suite before checkin
• Run Slow suite in Continuous Integration
• When appropriate, convert Selenium tests into unit tests
• Consider bootstrapping with Selenium tests, then replacing them with
isolated tests once your app is up and running
Slow-lenium
• Specify how to locate an HTML element
• id
• "id" attribute
• e.g. id=userName
• name
• "name" attribute
• followed by optional "value" or "index" filter
• e.g. name=flavor value=chocolate
Locators
Locators (cont.)
• identifier
• first id, then name
• dom
• JavaScript expression
• e.g. dom=document.forms['icecreamForm'].flavorDropdown
• xpath
• e.g. xpath=//a[contains(@href,'#id1')]/@class
Locators (cont.)
• link
• selects the <A>` element whose Text content matches the given text
• e.g. link=Click Here To Continue
• css
• css selector
• e.g. css=a[href="#id3"]
• Custom Locators
• By default, it's "identifier",
• or "xpath" if it starts with "//"
• or "dom" if it starts with "document."
• use ids when possible
• XPath makes your tests brittle and dependent on page structure
• use slow mode for debugging
• user_extensions.js
Tips
• Disable Transactional Fixtures for Selenium tests
• Reload all fixtures before every test
• consistent state
• order-independent
• set allow_concurrency=true
• cookies stay between tests
• can lead to tests passing when run alone, failing when run together
• you can eval JS to clear cookies between tests
• Firefox profiles
Gotchas
• Some people like it, some don't
• Pro:
• Top-down
• When test passes, feature is done
• Stay close to well-defined customer requirements
• Con:
• Still vulnerable to edge cases
• Brittle in the face of UI changes
• You usually iterate through all layers of tests, several times over
Test-driving from Selenium
• launches server locally
• runs tests locally and/or remotely
Pivotal rake integration
• selenium_suite.rb
• selenium_helper.rb
Pivotal Ruby Classes
• Generates HTML (FIT-style)
• Can't go into your DB or domain
• Any custom test code has to be JavaScript
• Does it work remotely?
Selenium On Rails
Q&A
Experimentation
• www.openqa.org—selenium-rc <http://www.openqa.org/selenium-rc/>
References
• 90 minutes with Q&A interspersed
Timeline
full-stack-webapp-testing-with-selenium-and-rails.pdf

More Related Content

Similar to full-stack-webapp-testing-with-selenium-and-rails.pdf

How To Use Selenium Successfully
How To Use Selenium SuccessfullyHow To Use Selenium Successfully
How To Use Selenium SuccessfullyDave Haeffner
 
Web testing with selenium and by quontra solutions
Web testing with selenium and  by quontra solutionsWeb testing with selenium and  by quontra solutions
Web testing with selenium and by quontra solutionsQUONTRASOLUTIONS
 
How To Use Selenium Successfully (Java Edition)
How To Use Selenium Successfully (Java Edition)How To Use Selenium Successfully (Java Edition)
How To Use Selenium Successfully (Java Edition)Sauce Labs
 
Effective out-of-container Integration Testing
Effective out-of-container Integration TestingEffective out-of-container Integration Testing
Effective out-of-container Integration TestingSam Brannen
 
Testing mit Codeception: Full-stack testing PHP framework
Testing mit Codeception: Full-stack testing PHP frameworkTesting mit Codeception: Full-stack testing PHP framework
Testing mit Codeception: Full-stack testing PHP frameworkSusannSgorzaly
 
Improving Your Selenium WebDriver Tests - Belgium testing days_2016
Improving Your Selenium WebDriver Tests - Belgium testing days_2016Improving Your Selenium WebDriver Tests - Belgium testing days_2016
Improving Your Selenium WebDriver Tests - Belgium testing days_2016Roy de Kleijn
 
jQuery Proven Performance Tips & Tricks
jQuery Proven Performance Tips & TricksjQuery Proven Performance Tips & Tricks
jQuery Proven Performance Tips & TricksAddy Osmani
 
Session on Selenium Powertools by Unmesh Gundecha
Session on Selenium Powertools by Unmesh GundechaSession on Selenium Powertools by Unmesh Gundecha
Session on Selenium Powertools by Unmesh GundechaAgile Testing Alliance
 
Escaping Test Hell - ACCU 2014
Escaping Test Hell - ACCU 2014Escaping Test Hell - ACCU 2014
Escaping Test Hell - ACCU 2014Wojciech Seliga
 
Selenium
SeleniumSelenium
Seleniumg2ix
 
Cross-browser unit testing JavaScript
Cross-browser unit testing JavaScriptCross-browser unit testing JavaScript
Cross-browser unit testing JavaScriptAlan Parkinson
 
Selenium Tutorial
Selenium TutorialSelenium Tutorial
Selenium Tutorialprad_123
 
Writing better tests for your java script app
Writing better tests for your java script appWriting better tests for your java script app
Writing better tests for your java script appJakeGinnivan
 
Selenium Tips & Tricks - StarWest 2015
Selenium Tips & Tricks - StarWest 2015Selenium Tips & Tricks - StarWest 2015
Selenium Tips & Tricks - StarWest 2015Andrew Krug
 
Galen Framework - Responsive Design Automation
Galen Framework - Responsive Design AutomationGalen Framework - Responsive Design Automation
Galen Framework - Responsive Design AutomationVenkat Ramana Reddy Parine
 

Similar to full-stack-webapp-testing-with-selenium-and-rails.pdf (20)

Selenium Concepts
Selenium ConceptsSelenium Concepts
Selenium Concepts
 
Selenium
SeleniumSelenium
Selenium
 
How To Use Selenium Successfully
How To Use Selenium SuccessfullyHow To Use Selenium Successfully
How To Use Selenium Successfully
 
Web testing with selenium and by quontra solutions
Web testing with selenium and  by quontra solutionsWeb testing with selenium and  by quontra solutions
Web testing with selenium and by quontra solutions
 
How To Use Selenium Successfully (Java Edition)
How To Use Selenium Successfully (Java Edition)How To Use Selenium Successfully (Java Edition)
How To Use Selenium Successfully (Java Edition)
 
Effective out-of-container Integration Testing
Effective out-of-container Integration TestingEffective out-of-container Integration Testing
Effective out-of-container Integration Testing
 
Automated ui-testing
Automated ui-testingAutomated ui-testing
Automated ui-testing
 
Testing mit Codeception: Full-stack testing PHP framework
Testing mit Codeception: Full-stack testing PHP frameworkTesting mit Codeception: Full-stack testing PHP framework
Testing mit Codeception: Full-stack testing PHP framework
 
Improving Your Selenium WebDriver Tests - Belgium testing days_2016
Improving Your Selenium WebDriver Tests - Belgium testing days_2016Improving Your Selenium WebDriver Tests - Belgium testing days_2016
Improving Your Selenium WebDriver Tests - Belgium testing days_2016
 
jQuery Proven Performance Tips & Tricks
jQuery Proven Performance Tips & TricksjQuery Proven Performance Tips & Tricks
jQuery Proven Performance Tips & Tricks
 
Session on Selenium Powertools by Unmesh Gundecha
Session on Selenium Powertools by Unmesh GundechaSession on Selenium Powertools by Unmesh Gundecha
Session on Selenium Powertools by Unmesh Gundecha
 
Escaping Test Hell - ACCU 2014
Escaping Test Hell - ACCU 2014Escaping Test Hell - ACCU 2014
Escaping Test Hell - ACCU 2014
 
Selenium.pptx
Selenium.pptxSelenium.pptx
Selenium.pptx
 
33rd degree
33rd degree33rd degree
33rd degree
 
Selenium
SeleniumSelenium
Selenium
 
Cross-browser unit testing JavaScript
Cross-browser unit testing JavaScriptCross-browser unit testing JavaScript
Cross-browser unit testing JavaScript
 
Selenium Tutorial
Selenium TutorialSelenium Tutorial
Selenium Tutorial
 
Writing better tests for your java script app
Writing better tests for your java script appWriting better tests for your java script app
Writing better tests for your java script app
 
Selenium Tips & Tricks - StarWest 2015
Selenium Tips & Tricks - StarWest 2015Selenium Tips & Tricks - StarWest 2015
Selenium Tips & Tricks - StarWest 2015
 
Galen Framework - Responsive Design Automation
Galen Framework - Responsive Design AutomationGalen Framework - Responsive Design Automation
Galen Framework - Responsive Design Automation
 

Recently uploaded

"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Neo4j
 
Bluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdfBluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdfngoud9212
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
Science&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdfScience&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdfjimielynbastida
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 

Recently uploaded (20)

"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024
 
Bluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdfBluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdf
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptxVulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
Science&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdfScience&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdf
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 

full-stack-webapp-testing-with-selenium-and-rails.pdf

  • 1. • Alex Chaffee • Brian Takita Full-stack webapp testing with Selenium and Rails
  • 2. • Want to test your entire Web 2.0 app, from AJAX and DHTML through browser-rendered HTML into a live instance of your application and database? Most web testing frameworks have gaps in their coverage: JUnit and Test::Unit miss the client frontend; JSUnit misses the server backend; web testing frameworks miss some or all of the JavaScript. With Selenium we have a framework that can test the whole application, from browser-executed JavaScript, through a live application backend, then back to assertions on browser-rendered DOM code. Selenium RC takes this further: since you write your tests in your application language, your tests can do data setup and assertions based directly on server-side domain objects that may be inaccessible or only partially accessible from the client side. On our teams we have used and developed a series of helper methods and assertions that allow testing of AJAX and DHTML functions as well. In this tutorial we outline the architecture of Selenium RC and walk through code and examples illustrating how to do full-stack testing against a Ruby on Rails application. Abstract
  • 3. • Selenium runs in the browser • Executes your app in a frame • Simulates user actions via JavaScript • Goes all the way to the server and back • Complementary to JSUnit • JSUnit tests JS pages only, not interaction with server • Fun to watch Selenium Features
  • 4. • Basic example (login_test.rb) • def test_login open "/" assert_text_present("Please sign in") type "username", "jdoe" type "password", "password" click "submit" assert_text_present("Welcome, John Doe") open "/" assert_text_present("Welcome, John Doe") end • Sort of a DSL ("Selenese") • Written in Ruby • Can also use Java, .NET, Python, Perl, etc. First Example
  • 5. • Can access database and/or domain objects • def test_signup open "/signup" assert_text_present("Please sign up") type "username", "noob" type "fullname", "New Bie" type "password", "secret" type "password_verify", "secret" click "submit" assert_text_present("Welcome, New Bie") user = User.find_by_username("noob") assert user.authenticate("secret") end Accessing Your World
  • 6. • def test_signup_via_email open "/signup" assert_text_present("Please sign up") type "email", "noob@example.com" click "submit" assert_text_present("An email has been sent to noob@example.com") wait_for { !ActionMailer::Base.deliveries.empty? } user = User.find_by_email("noob@example.com”) assert !user.verified? link = extract_link(ActionMailer::Base.deliveries[0].body) open link wait_for do user.reload user.verified? end end def extract_link(s) /http://S*/.match(s)[0] end Or even email!
  • 7. • def test_signup_via_email open "/signup" assert_text_present("Please sign up") type "email", "noob@example.com" click "submit" assert_text_present("An email has been sent to noob@example.com") wait_for { !ActionMailer::Base.deliveries.empty? } user = User.find_by_email("noob@example.com”) assert !user.verified? link = extract_link(ActionMailer::Base.deliveries[0].body) open link wait_for do user.reload user.verified? end end def extract_link(s) /http://S*/.match(s)[0] end Or even email!
  • 8. • def test_signup_via_email open "/signup" assert_text_present("Please sign up") type "email", "noob@example.com" click "submit" assert_text_present("An email has been sent to noob@example.com") wait_for { !ActionMailer::Base.deliveries.empty? } user = User.find_by_email("noob@example.com”) assert !user.verified? link = extract_link(ActionMailer::Base.deliveries[0].body) open link wait_for do user.reload user.verified? end end def extract_link(s) /http://S*/.match(s)[0] end Or even email!
  • 9. • def test_signup_via_email open "/signup" assert_text_present("Please sign up") type "email", "noob@example.com" click "submit" assert_text_present("An email has been sent to noob@example.com") wait_for { !ActionMailer::Base.deliveries.empty? } user = User.find_by_email("noob@example.com”) assert !user.verified? link = extract_link(ActionMailer::Base.deliveries[0].body) open link wait_for do user.reload user.verified? end end def extract_link(s) /http://S*/.match(s)[0] end Or even email!
  • 10. • def test_signup_via_email open "/signup" assert_text_present("Please sign up") type "email", "noob@example.com" click "submit" assert_text_present("An email has been sent to noob@example.com") wait_for { !ActionMailer::Base.deliveries.empty? } user = User.find_by_email("noob@example.com”) assert !user.verified? link = extract_link(ActionMailer::Base.deliveries[0].body) open link wait_for do user.reload user.verified? end end def extract_link(s) /http://S*/.match(s)[0] end Or even email!
  • 11. And don’t forget to extract a DSL def login(user_name,password) open('/login') type "id=login", user_name type "id=password", password click_and_wait "commit" end def logout open('/logout') end
  • 12. Remote (possibly) Selenium Test Suite Webrick running app (in "test" mode) Selenium Server Browser DOM/JS Launch Browser rake selenium:server rake selenium:test Launch Launch Database Launch Browser Selenium RC Architecture: launch
  • 13. Remote (possibly) Selenium Test Suite Webrick running app (in "test" mode) def test_foo click "submit" end Selenium Server Browser Selenese Interpreter DOM/JS click 'submit' click 'submit' Proxy HTTP HTTP rake selenium:server rake selenium:test Launch Launch Database Selenium RC Architecture: run test
  • 14. • OS (Unix, Windows, Mac) • Browser (IE, Firefox, Safari) • The Selenium Farm (Continuous Integration) Multiple Platform Support
  • 15. • Web 2.0 is Asynchronous and Dynamic • The “A” in "AJAX" • The "D" in "DHTML" • The problem: • Since they happen unpredicatably, and inside the context of a single page, they’re harder to test Good Things Come To Those Who Wait
  • 16. • wait_for function • executes in Ruby • wait_for_condition action • takes a JavaScript expression, evals it in browser • wait_for_condition is complementary to wait_for • JavaScript can't poll DB or domain objects • Write your conditions in the language you prefer Good Things Come To Those Who Wait
  • 17. • Tracker • project_page_editing_test • Peer2Patent • create_prior_art_test • registration_mode_test More examples
  • 18. • Integration Tests • Test multiple layers of your app working together • Acceptance Tests • Test specific customer features and/or scenarios • UI tests • Test complicated or detailed UI widgets • Smoke Tests • Special case of Integration Tests • Make sure your app doesn’t blow up What kind of tests?
  • 19. • Selenium tests are integration tests in the abstract • Not derived from Rails Integration Tests • Rails ITs are faster • Selenium tests are better for testing AJAX, DHTML, widgets, full-stack integration • Where you can do a test in Ruby instead of Selenium... you should. Wait, do you mean Integration Tests or Integration Tests?
  • 20. • Test full stack • Test JS->server interaction • Test emails • Smoke testing • Testing in multiple browsers When to use Selenium?
  • 21. Particular Strengths of Selenium Tests • AJAX/RJS tests • Test what state the browser is in after the RJS/AJAX call • JS tests • Test JavaScript interacting with your DOM • Not just functional/behavioral JS (which JSUnit is great for)
  • 22. • For every edge case • Want to test happy path, and one or two error paths • When speed is of the essence • e.g. in a suite you run a lot, or when your tests start taking more than a few minutes • see next slide... • When you’re testing fine-grained features • Selenium tests tend to sprawl out • setup/teardown are more expensive, so you want to test more things per test • Unit tests should be small and isolated When not to use Selenium?
  • 23. • Selenium is much faster than a human, but still much slower than unit tests. How do we deal with that? • Fast Suite / Slow Suite • Run Fast suite before checkin • Run Slow suite in Continuous Integration • When appropriate, convert Selenium tests into unit tests • Consider bootstrapping with Selenium tests, then replacing them with isolated tests once your app is up and running Slow-lenium
  • 24. • Specify how to locate an HTML element • id • "id" attribute • e.g. id=userName • name • "name" attribute • followed by optional "value" or "index" filter • e.g. name=flavor value=chocolate Locators
  • 25. Locators (cont.) • identifier • first id, then name • dom • JavaScript expression • e.g. dom=document.forms['icecreamForm'].flavorDropdown • xpath • e.g. xpath=//a[contains(@href,'#id1')]/@class
  • 26. Locators (cont.) • link • selects the <A>` element whose Text content matches the given text • e.g. link=Click Here To Continue • css • css selector • e.g. css=a[href="#id3"] • Custom Locators • By default, it's "identifier", • or "xpath" if it starts with "//" • or "dom" if it starts with "document."
  • 27. • use ids when possible • XPath makes your tests brittle and dependent on page structure • use slow mode for debugging • user_extensions.js Tips
  • 28. • Disable Transactional Fixtures for Selenium tests • Reload all fixtures before every test • consistent state • order-independent • set allow_concurrency=true • cookies stay between tests • can lead to tests passing when run alone, failing when run together • you can eval JS to clear cookies between tests • Firefox profiles Gotchas
  • 29. • Some people like it, some don't • Pro: • Top-down • When test passes, feature is done • Stay close to well-defined customer requirements • Con: • Still vulnerable to edge cases • Brittle in the face of UI changes • You usually iterate through all layers of tests, several times over Test-driving from Selenium
  • 30. • launches server locally • runs tests locally and/or remotely Pivotal rake integration
  • 32. • Generates HTML (FIT-style) • Can't go into your DB or domain • Any custom test code has to be JavaScript • Does it work remotely? Selenium On Rails
  • 33. Q&A
  • 36. • 90 minutes with Q&A interspersed Timeline