How To Test Responsive Web Apps with Selenium
Sauce AI for Test Authoring: Move from design to execution in minutes.|xBack to ResourcesBlogPosted
Sauce AI for Test Authoring: Move from design to execution in minutes.
|
x
The Problem
When testing a web covering with a reactive layout you & # x27; ll want to verify that it renders the page right in the mutual resoluteness your users use. But how do you do it?
Historically this type of substantiation has been performmanually at the endof a development workflow -- which tends to leave to delay and visual shortcoming getting released into production.
A Solution
We can easily sidestep these concerns by automating responsive layout testing so we can get feedback fast. This can be done with a Selenium test,, and.
Let & # x27; s dig in with an example.
An Example
NOTE: This example is built using Ruby and the RSpec testing framework. To play along, you & # x27; ll need Applitools Eyes and Sauce Labs accounts. They both have free trial accounts which you can subscribe up for and (no credit card required).
Let & # x27; s test the responsive layout for the login of a website (e.g., the one found onthe-internet).
In RSpec, a test file is advert to as a & quot; spec & quot; and end_spec.rb. So our test file will belogin_spec.rb. We & # x27; ll start it by command our requisite libraries (e.g.,selenium-webdriverto drive the browser andeyes_seleniumto connect to Applitools Eyes) and specifying some initial configuration values with sensitive defaults.
[codification language= & quot; ruby & quot;]
# filename: login_spec.rb
require & # x27; selenium-webdriver & # x27;
require & # x27; eyes_selenium & # x27;
ENV [& # x27; browser & # x27;] ||= & # x27; internet_explorer & # x27;
ENV [& # x27; browser_version & # x27;] ||= & # x27; 9 & # x27;
ENV [& # x27; platform & # x27;] ||= & # x27; Windows 7 & # x27;
ENV [& # x27; viewport_width & # x27;] ||= & # x27; 1000 & # x27;
ENV [& # x27; viewport_height & # x27;] ||= & # x27; 600 & # x27;
# ...
[/code]
By using Ruby & # x27; s||=operator we & # x27; re able to specify nonpayment values for these surroundings variable. These default values will be employ if we don & # x27; t specify a value at run time (more on that later).
Next we ask to configure our test setup so we can get a browser representative from Sauce Labs and connect it to Applitools Eyes.
[codification language= & quot; ruby & quot;]
# filename: login_spec.rb
# ...
describe & # x27; Login & # x27; do
before (: each) do |example|
caps = Selenium: :WebDriver: :Remote: :Capabilities.send (ENV [& # x27; browser & # x27;])
caps.version = ENV [& # x27; browser_version & # x27;]
caps.platform = ENV [& # x27; platform & # x27;]
caps [: gens] = example.metadata [: full_description]
@ browser = Selenium: :WebDriver.for (
:remote,
url: & quot;,
desired_capabilities: caps)
@ eyes = Applitools: :Eyes.new
@ eyes.api_key = ENV [& # x27; APPLITOOLS_API_KEY & # x27;]
@ driver = @ eyes.open (
app_name: & # x27; the-internet & # x27;,
test_name: example.metadata [: full_description],
viewport_size: {width: ENV [& # x27; viewport_width & # x27;] .to_i,
height: ENV [& # x27; viewport_height & # x27;] .to_i},
driver: @ browser)
end
# ...
[/code]
In RSpec you specify a test suite with the worddescribefollowed by the name as a string and the worddoat the end (e.g.,describe & # x27; Login & # x27; do).
We want our test setup to run before each test. To do that in RSpec we usebefore (: each) do. And to gain access to test details (e.g., the test name) we append a variable name in pipes to the incantation (e.g.,before (: each) do |example|).
To hold the browser and operating scheme we use a Selenium Remote Capabilities object (e.g.,Selenium: :WebDriver: :Remote: :Capabilities.send (ENV [& # x27; browser & # x27;])). With it we & # x27; re also able to determine the name of the exam so it shows up aright in the Sauce Labs job. We then connect to Sauce Labs by using Selenium Remote (specifying our certification in the URL), surpass our capableness object to them (e.g.,desired_capabilities: caps), and storing the browser instance they provide in an instance variable (e.g.,@browser).
Then we open a connection with Applitools Eyes by creating an instance of the Applitools Eyes objective (e.g.,@ eyes = Applitools: :Eyes.new), specifying the API key, and calling@ eyes.open(providing the covering name, test name, viewport size, and the browser case from Sauce Labs). This returns a Selenium object that is connected to both the browser instance in Sauce Labs and Applitools Eyes. We store this in another instance variable (e.g.,@driver) which we & # x27; ll to drive the browser in our test.
After each test runs we & # x27; ll want to fold the Applitools Eyes session and destroy the browser instance in Sauce Labs. To do that in RSpec, we & # x27; ll place the necessary commands in useafter (: each) do.
[code language= & quot; ruby & quot;]
For autonomous testing across multiple user personas, check out SUSATest — it explores your app like 10 different real users.
# filename: login_spec.rb
# ...
after (: each) do
@ eyes.close
@ browser.quit
end
# ...
[/code]
Now we & # x27; re ready to compose our test. In it we will have entree to two example variable. One for the Selenium browser instance in Sauce Labs (e.g.,@driver) and another for the job in Applitools Eyes (e.g.,@eyes).
[code language= & quot; ruby & quot;]
# filename: login_spec.rb
# ...
it & # x27; succeeded & # x27; do
@ driver.get & # x27;http: //the-internet.herokuapp.com/login'
@ eyes.check_window (& # x27; Login Page & # x27;)
@ driver.find_element (id: & # x27; username & # x27;) .send_keys (& # x27; tomsmith & # x27;)
@ driver.find_element (id: & # x27; password & # x27;) .send_keys (& # x27; SuperSecretPassword! & # x27;)
@ driver.find_element (id: & # x27; login & # x27;) .submit
@ eyes.check_window (& # x27; Logged In & # x27;)
end
end
[/code]
Tests in RSpec are specified with the wordit, a string name for the test, and the tidingsdo (e.g., it & # x27; succeeded & # x27; do).
Our trial is bare. It visits the login page and complete the login form with two visual verifications being performed -- one after the page loads and another after completing the login.
If we save this file and run it (e.g.,rspec login_spec.rbfrom the command-line) it will act in a single screen resolution (e.g., 1000x600). Now let & # x27; s make it so we can specifymultiplescreen resolutions and hold it run the same test on all of them. To do that we & # x27; ll need a little help from a library calledRake.
Packaging Things Up
With Rake we can create a file (e.g.,Rakefile) and store tasks in it (using Ruby syntax) that we can telephone from the command line.
Let & # x27; s create a task that will handle executing our test for each screen resolution we wantin parallel.
[code language= & quot; ruby & quot;]
# filename: Rakefile
desc & # x27; Run examination against each screen firmness we care about & # x27;
task: run do
RESOLUTIONS = [{width: & # x27; 1000 & # x27;, height: & # x27; 600 & # x27;},
{width: & # x27; 414 & # x27;, height: & # x27; 699 & # x27;},
{breadth: & # x27; 320 & # x27;, height: & # x27; 568 & # x27;}]
threads = []
RESOLUTIONS.each do |resolution|
threads & lt; & lt; Thread.new do
ENV [& # x27; viewport_width & # x27;] = resolution [: breadth]
ENV [& # x27; viewport_height & # x27;] = resolution [: height]
system (& quot; rspec login_spec.rb & quot;)
end
end
threads.each {|thread| thread.join}
end
[/code]
In Rake you can render a descriptor for a task with the keyworddescfollowed by the description text in a string (e.g.,desc & # x27; Run tryout ... & # x27;). Tasks are set by thetaskkeyword followed by the name of the task (specified as a symbolisation) and ending with the intelligencedo (e.g., task: run do).
We depart our:runjob off by specify the screen declaration we want in key/value span (a.k.a. a hash) inside of an array (a.k.a. a collection). This enable us to easily restate through the collection (e.g.,RESOLUTIONS.each do |resolution|) and grab out the width and height values for each resolution. When we do that we & # x27; re storing them in environment variables (e.g.,ENV [& # x27; viewport_width & # x27;] = resolution [: width]) which are likewise used in our test code. So when we run our test (e.g.,system (& quot; rspec login_spec.rb & quot;)) it will be using the correct width and height values.
NOTE: The resolve utilise hither will trigger different blind layouts (e.g., desktop, voguish earpiece, etc.). For a true test of your app, be certain to look at your usage analytics to see what screen firmness your exploiter are utilize.
For each loop of our screen declaration we & # x27; re make a new thread, which will make each examination run at the same clip. So when we run this task, our single Selenium test will get fulfill three times (once for each firmness specified), and each run will use a difference blind resolution.
After saving this file we can do a flying sanity tab to do sure rake runs and the task is listed by releaserake -Tfrom the command-line.& gt; rake -T rake run # Run tests against each screen firmness we care about
To run this project it & # x27; s as simple asrake runfrom the command line. And to delimitate a different browser, browser adaptation, or platform you simply need to prepend the command with different values.browser=internet_explorer browser_version=8 platform= & quot; Windows XP & quot; rake run browser=firefox browser_version=37 rake run browser=safari browser_version=8 platform= & quot; OS X 10.10 & quot; rake run browser=chrome browser_version=40 platform= & quot; OS X 10.8 & quot; rake run
See the for a full inclination of available browser/OS combinations.
Expected Behavior
If we run this (e.g.,rake runfrom the command-line) here is what will happen:
The test will run numerous times (in latitude) -- once for each resolution specify
Each test will retrieve a browser instance from Sauce Labs and associate it to Applitools Eyes with the correct screen resolution
The test will run and perform its optical check
The browser case on Sauce Labs and connecter to Applitools Eyes will close
The results for the job will be displayed in the end output
When the rake task is complete, you can regard the visual checks for each declaration in. Each resolution will have it & # x27; s own job. In each job you can either have or reject the result. Accepting will set it as the baseline for subsequent test runs. If you do nothing, then the termination will mechanically be used as the baseline. You can besides see each of the exam escape in entire detail (e.g., video, screenshots, Selenium log, etc.) in.
On each subsequent run, if there is a visual anomaly for any of the given resolutions specified then the test will fail for that resolution -- and you & # x27; ll be able to easily name it.
Outro
Hopefully this tip has helped you add automated responsive layout screen to your suite, enabling you to get ocular layout bugs early on in your development workflow.
For reference, you can see the full codification exemplarhere.
Happy Testing!
About Dave Haeffner:Dave is the generator ofElemental Selenium(a free, erst weekly Selenium tip newssheet that is read by hundred of testing professionals) as well as a new book,The Selenium Guidebook. He is also the creator and sustainer ofChemistryKit(an open-source Selenium framework). He has helped numerous society successfully apply automated acceptance testing; including The Motley Fool, ManTech International, Sittercity, and Animoto. He is a beginner and co-organizer of theSelenium Hangoutand has spoken at numerous conferences and meetups about credence examination.
Automate This With SUSA
Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts needed.
Try SUSA FreeTest Your App Autonomously
Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.
Try SUSA Free