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.
Join the DZone community and get the full member experience.
Join For FreeRecently, 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:
- Read the URL through Image.IO and pass it to a BufferedImage.
- Pass the BufferedImage to BufferedImageLuminanceSource Zxing class.
- 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.
- 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.
Decode the Base64 String in a array of bytes
Pass the decoded String to ImageIO.read parameter. Here you need to instantiate a new ByteArrayInputStream
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.
Published at DZone with permission of Elias Nogueira. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments