Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Read QR Code Content With Selenium and zxing

DZone's Guide to

Read QR Code Content With Selenium and zxing

Learn about a library for Selenium Webdriver that allows you to read the content of a QR code on a webpage and use it in the subsequent test.

· DevOps Zone ·
Free Resource

Monitor your CI/CD pipelines end-to-end with Hygieia, an open source dashboard from Capital One.

Recently, one of my teams faced a technical problem: read a QR code from a web page to use for an authorization process. As we need to create an E2E test to guarantee the user journey, the main problem is how to read the content of a QR code, on a webpage, and use it in the subsequent test.

As we use Selenium WebDriver with Java as the programming language, the main challenge was finding a library (in Java) to read the QR code.

Reading a QR Code

ZXing (“zebra crossing”) is an open-source, multi-format 1D/2D barcode image processing library implemented in Java, with ports to other languages. One supported 2D format is the QR code.

The first thing we did was add the ZXing library to our project classpath. Below is the snippet in a pom.xml file (Maven)

<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>3.3.0</version>
</dependency>

<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>javase</artifactId>
    <version>3.3.0</version>
</dependency>

After we've created a way to receive an URL and decode the QR Code.
The simple steps are:

  1. Read the URL through Image.IO and pass it to a BufferedImage.
  2. Pass the BufferedImage to BufferedImageLuminanceSource Zxing class.
  3. Instantiate the class HybridBinarizer, that is responsible to read the 2D barcode (QR Code), with BufferedImageLuminanceSource as a parameter and create a new BinaryBitmap, to prepare to decode the 2D barcode.
  4. Instantiate a MultiFormatReader calling the decode method passing the BinaryBitmap. The MultiFormatReader is a convenience class and will attempt to decode all barcode formats that the library supports. The result is a Result class that encapsulates the result of decoding a barcode within an image.

So we created a function to do all this magic…

private static String decodeQRCode(URL qrCodeImage) throws IOException, NotFoundException {
    BufferedImage bufferedImage = ImageIO.read(qrCodeImage);
    LuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
    BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

    Result result = new MultiFormatReader().decode(bitmap);
    return result.getText();
}


How about Selenium?

Now we just need to find the QR Code on the page, through the element image (probably) and get the src attribute.

An example may be found at the github example (in the end of this post). The code bellow is a Selenium snippet to find an element by the id "qr" (and image) and get the attribute src.

String qrCodeFile = driver.findElement(By.id("qr")).getAttribute("src");

E.g: https://eliasnogueira.github.io/selenium-read-qrcode/qrcode.png

After that we just pass this String to decodeQRCode method (the example above) and the result will the QR Code content. In this example the QR Code is a text "QR Code output text".

Voilà! Easily we have a code that read a QR Code image on a webpage!


But, if the QR Code come from a Base64 instead of URL?

A few things in the code will change.

  1. Decode the Base64 String in a array of bytes

  2. Pass the decoded String to ImageIO.read parameter. Here you need to instantiate a new ByteArrayInputStream

  3. The rest of the code don't change

Example:

private static String decodeQRCode(String base64QRCode) throws IOException, NotFoundException {
byte[] decoded = Base64.decodeBase64(base64Source);
BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(base64QRCode));
    LuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
    BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

    Result result = new MultiFormatReader().decode(bitmap);
    return result.getText();
}


Note that I have changed the method decodeQRCode to expect a String parameter.
You can appy some logic to just have one method and try to realize if it's a URL or Base64 String.

The github example


The complete and functional example may be found at https://github.com/eliasnogueira/selenium-read-qrcode

There's just one method to decode the image that figure out if the parameter is a URL or Base64 image and two test to assert this logic.

Track and monitor your entire CI/CD pipeline on a single pane of glass. Hygieia is an open source, visual dashboard for keeping CI/CD pipelines green.

Topics:
java ,devops ,software testing ,selenium ,selenium webdriver

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}