Automated Testing QRCodes in Selenium WebDriver

How to test QRCodes on a webpage

Courtney Zhan
4 min readApr 24, 2022


QR Codes are becoming a more and more common method of link sharing, but how can we test that the QRCode you generated goes where it needs to go?

QRCodes are a barcode that can be scanned with a camera app or dedicated scanner. They have been growing in popularity because of COVID-19 and are commonplace now (at least in Australia!). Most websites and apps use QR Codes as a shortcut link (e.g. scan this QR Code to order for Table 12).

This tutorial will show you how to test that a valid QRCode was created and verify it successfully goes to a particular URL.

Tutorial Website

The WhenWise app has a QRCode for directly booking an appointment with a staff member. The below QRCode is an example on a server running locally for testing purposes (if you try to scan it, it won’t work).

I plan to write a test script to verify the QRCode generation.

Test Design

  1. Save the QR Code image
    Selenium 4 supports saving an individual page element to an image. Typically, generated QR codes are in SVG format, not conventional bitmap images formats such as PNG.
  2. Read the QR code
    We need to decode the QR code to text. This can be achieved from a library.
    (The availability of many libraries is one great benefit of writing automated tests in a powerful scripting language such as Ruby.)
  3. Verify the URL
    Determine the expected URL first, then compare it with the decoded text from the QR code.


I use qrio, a QR code decoder in pure Ruby. Install it on your command line with:

gem install qrio

QRio can load an image of a QR Code and then extract its text. Example usage from the documentation is:

require 'qrio'
qr_decoded = Qrio::Qr.load("qr-code.png").qr.text

Save the QR Code image

To save the QR Code, we can use Selenium 4’s built-in elem.save_screenshot(output_file_path) function.

To save our QR Code we would run this on the page with the code:

# defining a relative path for saving the image to
tmp_dir = File.expand_path File.join(File.dirname(__FILE__), "..", "..", "tmp")
dest_image_file_path = File.join(tmp_dir, "qr_code.png")
# locate the QR Code element
elem_qrcode = driver.find_element(:tag_name, "svg")
# save the image

If you execute this, the QRCode image will be saved under ../../tmp/qr_code.png. Now we can start decoding it with QRio and do our verification.

Before we finish, I recommend doing some post-script clean up. During the test, we save the QRCode. However, we probably want to delete it after the test completes so we are not left with unnecessary files that could interfere with future test executions.

Complete Test Script

it "Verify QRCode" do
require "qrio"
human_resource_page =

expected_qrcode_url = driver.find_element(:id, "booking-qrcode")["href"]
puts "Expected => #{expected_qrcode_url}"
# save the qr code image
tmp_dir = File.expand_path File.join(File.dirname(__FILE__), "..", "..", "tmp")
dest_image_file_path = File.join(tmp_dir, "qr_code.png")

elem_qrcode = driver.find_element(:tag_name, "svg")

# read the qr code
qr_code_text = Qrio::Qr.load(dest_image_file_path).qr.text
puts "Scanned => #{qr_code_text}"
# assert qr code url is correct
expect(qr_code_text).to eq(expected_qrcode_url)


  • Find the QR Code element
    Here I used the tag_name locator, as there is only one SVG image on the WhenWise site. If there are more, use find_elements(:tag_name, ...).last or an XPath locator.
  • Save the QR code image
    Using Selenium’s elem.save_screenshot 0(v4).
    Note: I suggest using a relative path, it’s good practice.
  • Decode the QR code from the saved image
    Using the qrio library. There are other libraries in Ruby (and other languages as well), but I have not encountered any problems with QRio.

Test Execution (in TestWise)

Below is a screenshot after execution in TestWise.

Test results and output in TestWise testing IDE

In the console at the bottom right, the expected and scanned QRCode’s URLs are printed. Both are the same — so the test passes successfully!

The full execution can be seen in the gif below.