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)

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.

 

Function to DecodeQRcode

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.

The code bellow is a Selenium snippet to find an element by the id “qr” (and image) and get the attribute src.

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”.

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 apply some logic to just have one method and try to realise if it’s a URL or Base64 String.

The complete and functional example may be found at https://gitlab.pramati.com/lakshmikanthana/selenium-readqrcode.git

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

 

Written By: Lakshmikanthan