Pages

Wednesday, December 15, 2021

 Read and Verify QR code with Zxing and Appium

In every day life, we are witnessed about new technologies update. This is good for users as it helps to get every process easy and faster. QR code is now very common. Appium does not provide any support to handle QR code. For Automation, its not easy to handle such type of feature. Generally we should avoid to automate features that interact with hardware until we don't have a stable solution.

Here I am sharing solution for Read and Validating QR code with Appium and Zxing which is quite stable.

Approach: 

An easy solution is to take a screenshot from the device screen, get the points (width and height) from the element on the device, and crop the image to the element size, so you have an image with just the QR code. Now, you can use Zxing to read the QR code content.

Few Words about Zxing

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

Steps by step process

Here are all steps  


1. Add Zxing maven dependency to Pom.xml

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

2. Get QR code image from App using Appium

you can create an auxiliary method that receives a MobileElement (the element that contains the QR code) and a File (the device screenshot) to get the points and crop the device screenshot to the element size. We can crop image with the help of X,Y coordinate of QR code with help of function getX() and getY(). 

Here is the code snippet for capture a image and sub image

private BufferedImage generateImage(MobileElement element, File screenshot)
 throws IOException {
BufferedImage fullImage = ImageIO.read(screenshot);

Point imageLocation = element.getLocation();

int qrCodeImageWidth = element.getSize().getWidth();

int qrCodeImageHeight = element.getSize().getHeight();

int pointXPosition = imageLocation.getX();

int pointYPosition = imageLocation.getY();

BufferedImage qrCodeImage = fullImage.getSubimage(pointXPosition,
                pointYPosition, qrCodeImageWidth, qrCodeImageHeight);

ImageIO.write(qrCodeImage, "png", screenshot);

return qrCodeImage;

}

This function return buffered image of QR code

Now we have done with prerequisites i.e. cropped QR code's image.


3. Decode QR code from Cropped QR code using below function

Now we will pass cropped QR code's image and decodeQRCode function will return 

decoded informationbehind QR code in string format.

private static String decodeQRCode(BufferedImage qrCodeImage) throws
 NotFoundException {
LuminanceSource source = new BufferedImageLuminanceSource(qrCodeImage);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

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

4. Validate decoded information

Now we have actual decoded information and we also have expected result (Expected Decoded

 information of QR Code) so we can validate it. We have to invoke all above function and validate it.

 Here it is

public void readQRCode(String expectedDecodeInfo) throws
 IOException, NotFoundException {

MobileElement qrCodeElement = driver.findElement(By.id(
    "com.eliasnogueira.qr_code:id/qrcode"));

File screenshot = driver.getScreenshotAs(OutputType.FILE);



String actualDecodeInfo = decodeQRCode(generateImage(
                               qrCodeElement, screenshot));

System.out.println("content = " + actualDecodeInfo
);
Assert.assertTrue(actualDecodeInfo.equals(expectedDecodeInfo));
}

Now we are done :)

Monday, November 29, 2021

Verification from PDF File


Selenium or other automation framework is all about to automate browser. We do not have any feature to extract or parse text from PDF file or other file formats and verify it. Today we can see many applications are using PDF file formats specially for documentation. Generally we get a link when we click it opens PDF file. In such cases we skip this functionality to automate as we don not have any support in Selenium or other automation tools. I came across same problem so I am providing solution here.

Few words about library we are going to use


we are using Apache Tika for extracting data from PDF File, we can develop a content extractor to extract both structured text as well as metadata from different types of documents such as PDFs, spreadsheets, text documents, images and even multimedia input formats to a certain extent.




The parser interface of org.apache.tika.parser is the key interface for parsing documents in Tika. This Interface extracts the text and the metadata from a document and summarizes it for external users who are willing to write parser plugins.

How to use it?


If we are using maven project then we can simply use maven dependency for Apache Tika.

<dependency>
    <groupId>org.apache.tika</groupId>
    <artifactId>tika-parsers</artifactId>
    <version>1.24.1</version>
</dependency>

If you are using gradle then you can use

// https://mvnrepository.com/artifact/org.apache.tika/tika-parsers
implementation group: 'org.apache.tika', name: 'tika-parsers',
version: '2.1.0', ext: 'pom'
we have other dependency from Apache Tika but for parsing this is enough.

Code snippet for Parse Content from PDF file from URL (No need to download PDF file)

I have tried to write code with comments how it is working. Please have a look on code snippet.


public static String getTextFromPdf(String url) throws 
      IOException, TikaException, SAXException {

BodyContentHandler handler = new BodyContentHandler();
Metadata metadata = new Metadata();
InputStream inputstream =new URL(url).openStream();
ParseContext parsedContext = new ParseContext();
//parsing the document using PDF parser
PDFParser pdfparser = new PDFParser();
pdfparser.parse(inputstream, handler, metadata,parsedContext);
//getting the content of the document
System.out.println("Contents of the PDF :" + handler.toString());
//getting metadata of the document
System.out.println("Metadata of the PDF:");
String[] metadataNames = metadata.names();
for(String name : metadataNames) {
System.out.println(name+ " : " + metadata.get(name));
}
return handler.toString();
}


A sample test with parser function


@Test
public void verifyPDFContent() throws 
TikaException, IOException, SAXException {
String[] validationTexts = {"Enter", "Multiple", "Words", "From PDF"};
String textFromPdf= PdfParser.getTextFromPdf("Url of PDF File.");
Assert.assertTrue(Arrays.stream(validationTexts).parallel()
.allMatch(textFromPdf::contains));
}



I hope this small but useful blog will help you.