UI Test Automation with Karate

Tech Talk

by Engineers of Acroquest Myanmar Technology

UI Test Automation with Karate

Hello, I am Zin Hnin Wai, a DevOps Engineer of Acroquest Myanmar Technology.
I want to share how we can test the modules of our application or system automatically. I wrote a blog about “Karate Performance Testing with Gatling” in previous. You can read it from here.

Basically, developers need to execute unit or monkey testing by themselves. But it can cause inconvenient time usage of development. The automation of behaviours confirmation/testing is precious to us.


◆ What is Unit Testing?

Unit testing is to confirm the quality of coding by developers themselves. The purpose is to isolate each module of the system/application to detect defects and fix them in very early stage (development stage). So, it can reduce cost of testing as defects are detected early.

◆ Why should we use Karate?

  1. Can confirm target testing pattern with accurate result in every execution by configuring the specific input and output value
  2. Can reduce human resource’s workload
  3. Can reduce human careless mistake

◆ Getting started

1. Create sample Karate project in IntelliJ IDEA 2022.2.3(Community Edition)
(1.1) Create a new project.


(1.2) Setup Karate archetype
* Make sure the path of Java. Otherwise, maven build will be failed and cannot be created Karate project.
* In this sample project, Java 11 and maven 3.8.1 are used.


Add Archetype
GroupId : com.intuit.karate
ArtifactId : karate-archetype
Version : 1.3.0 (https://github.com/karatelabs/karate/releases)

Advanced Settings
* You can give your desire ones. *
GroupId : org.karatestudy
ArtifactId : uitest


(1.3) Generate project
(Maven automatically build the Karate project)


(1.4) Project folder structure
Below folder structure is generated automatically after maven build.


2. Create Karate scenarios and configure in karate-config.js

  • Create a folder, LogOutput under ‘uitest/’ to save chrome browser log.
  • Create Karate feature file and necessary classes
    • Create a folder, googleUI under src/test/java/examples/
    • Create google-search.feature and GoogleUIRunner.java under newly created folder(../googleUI/).
  • In google-search.feature,
    • There are two scenarios
      • Search function
      • Screen transition
        (I provided easy ones as sample. You can explore widely for testing UI of your system or project)

To know more about Actions to check UI in Karate, see here.

(2.1) Karate feature file : google-search.feature

 Feature: Sample Karate test script for testing google UI
   for details, see: https://github.com/karatelabs/karate/tree/master/karate-core
 
   Background:
     * configure driver = ({ userDataDir: userDir, headless: is_headless }) #A
 
   Scenario: search with text
     Given driver 'https://www.google.com/'
     * input('input[name=q]', 'car')
     * locate('.gNO89b').click()
     * match driver.url contains 'q=car'
 
   Scenario: Transit to Google About page
     Given driver 'https://www.google.com/'
     * delay(1000)
     * locate('.pHiOh').click()
     * waitUntil("document.title == 'Google - About Google, Our Culture & Company News'")
     * match driver.title == 'Google - About Google, Our Culture & Company News' 

#A: User data directory and headless options are defined in karate-config.js.
userDataDir: Combine all chrome logs in one directory to save disk space. Otherwise, one chrome log folder will be created whenever Karate is run.
headless: If it is false, chrome will be up to show every step of your Karate execution in browser(chrome). It can reduce your machine’s performance when you run many features.

karate-config.js :

 var config = {
  userDir: 'LogOutput',
  is_headless: true
  }; 

karate-config.js is to set up the ‘global’ variables and can get the current environment or profile. It is needed to exist on the ‘classpath’ and contain a JavaScript function. See example karate-config.js.

Karate feature file :

Background:
     * configure driver = ({ userDataDir: userDir, headless: is_headless })  

Variables must be exactly same. Otherwise, configuration in karate-config will not work well.

(2.2) Runner Class file : GoogleUIRunner.java
This class will not pick up when executing ‘mvn test’ from the command line. But you can invoke it from the IDE and it is convenient in development

package examples.googleUI;
 
 import com.intuit.karate.junit5.Karate;
 
 class GoogleUIRunner {
 
     @Karate.Test
     Karate testUsers() {
         return Karate.run("googleUI").relativeTo(getClass());
     }
 } 


3. Configure cucumber and Karate report in ExamplesTest.java

Cucumber is a tool that supports Behavior-Driven Development (BDD). It reads executable specifications written in the plain text and execute test according to those specifications. Moreover, it is not a browser automation tool, but it works well with other browser testing tool like Karate API/UI testing tool.

(3.1) Configuration for Karate is

@Test
void testParallel() {
   Results results = Runner.path("classpath:examples")
        //.outputCucumberJson(true) 
        .parallel(5); 
        assertEquals(0, results.getFailCount(), results.getErrorMessages());
} 

(3.2) Configuration for cucumber is

public static void generateReport(String karateOutputPath) {
         Collection<File> jsonFiles = FileUtils.listFiles(new File(karateOutputPath), new String[] { "json" }, true);
         List<String> jsonPaths = new ArrayList<String>(jsonFiles.size());
         jsonFiles.forEach(file -> jsonPaths.add(file.getAbsolutePath()));
         Configuration config = new Configuration(new File("target"), "karatestudy"); 
         ReportBuilder reportBuilder = new ReportBuilder(jsonPaths, config);
         reportBuilder.generateReports();
} 


(3.3) Full source code for both cucumber and Karate in ExamplesTest.java
ExamplesTest.java (*Test.java naming convention) will pick up when invoking ‘mvn test’ and acts test suite for entire project. Karate will load all features in the project.

package examples;
 
 import com.intuit.karate.Results;
 import com.intuit.karate.Runner;
 import static org.junit.jupiter.api.Assertions.*;
 import org.junit.jupiter.api.Test;
 
 import net.masterthought.cucumber.Configuration;
 import net.masterthought.cucumber.ReportBuilder;
 import org.apache.commons.io.FileUtils;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
 class ExamplesTest {
 
     @Test
     void testParallel() {
         Results results = Runner.path("classpath:examples")
                 .outputCucumberJson(true) #B
                 .parallel(5);
         generateReport(results.getReportDir()); #C
         assertEquals(0, results.getFailCount(), results.getErrorMessages());
     }
 
     public static void generateReport(String karateOutputPath) {
         Collection<File> jsonFiles = FileUtils.listFiles(new File(karateOutputPath), new String[] { "json" }, true); #Collect json file which is permitted at #B
         List<String> jsonPaths = new ArrayList<String>(jsonFiles.size());
         jsonFiles.forEach(file -> jsonPaths.add(file.getAbsolutePath()));
         Configuration config = new Configuration(new File("target"), "karatestudy"); #D
         ReportBuilder reportBuilder = new ReportBuilder(jsonPaths, config);
         reportBuilder.generateReports();
     }
 } 

#B: To generate cucumber json format file when running Karate features.
#C: To generate cucumber html report.
#D: To record html output folder.        
 (I defined as cucumber output directory is “target” to see both Karate and cucumber report in the same directory)

In order to convert from json format to html, net.masterthought.cucumber plugin is necessary to configure in pom.xml
*Don’t forget to reload maven project after pom.xml is changed.

<dependencies>         
     <dependency>
        -----
     </dependency>
     <!-- Reporting -->
     <dependency>
         <groupId>net.masterthought</groupId>
         <artifactId>cucumber-reporting</artifactId>
         <version>5.3.1</version>
         <scope>test</scope>
     </dependency>
 </dependencies> 


4. Project folder structure after adding requirements for Karate UI test


5. Execute Karate features

 To run single feature: 
 mvn test -Dtest=<Runner Class> 
 Example : mvn test -Dtest=ChromeUIRunner
 
 To run all features at once:
 mvn test 


6. Confirm the result

(6.1) In IntelliJ, testing result can be seen in Console log


(6.2) Default Karate report directory
uitest\target\karate-reports\ karate-summary.html


(6.3) Cucumber report directory
uitest\target\ cucumber-html-reports\ overview-features.html


Today I created a very simple project to test UI. As Karate is very effective automation tool, you can apply well it for your project requirements to capture defects in very early stage to reduce testing cost.

Thank you for taking time to read it.
See you again.

★★★We are hiring the staff who are interested in latest technologies.★★★

If you are interested in our company, please see the available job descriptions in the following links. Opening Jobs :
Opening Jobs

Check our Facebook Page!