Selenium WebUI automated testing framework

The framework is designed based on the PO model, splitting page elements and operations to reduce maintenance costs when the page is changed; at the same time, it uses xsd to customize xml tags and drives Selenium to execute by parsing xml, which reduces a certain amount of language learning costs.
The main function

  1. Concurrent execution based on selenium-grid
  2. Can be scripted based on xml
  3. Execution steps can insert custom functions
  4. Basic operations (click, hover, input, value comparison, switch iframe, switch page, close page, template matching, etc.)
  5. Test report collection

Design ideas

  1. Most of webUI automation is based on selenium
  2. PO model is the most widely used design pattern in webUI automation
  3. When selenium is executed, test data can be provided through DataProvider
  4. The common test data management methods are nothing more than the existence of db / the existence of local files, and they are all structured data
  5. Java has a DOM4J library, which can easily parse DOM documents. At the same time, XML in DOM can be flexibly defined and is relatively descriptive. Therefore, XML is selected as test data management so that there is a general running process of the framework.
    1. Initialize process data and basic configuration
    2. Initialize webDriver
    3. Traverse the parsed process data for execution
    4. Output test report
    5. Close webDriver

Obvious problems in the early stages of design
Q1: If you can only call built-in methods, the flexibility is not enough
A: Therefore, Spring is introduced as instance management, so that you only need to use the specified tag + beanName in the process data to implement the execution of the custom method.
Q2: WebUI automation usually takes too long to execute, how to shorten it?
A: Introduce selenium-grid for distributed execution and data isolation
Q3: Is there a more accurate and faster way to position elements?
A: Introducing image algorithms such as feature recognition, template matching, and OCR

Basic functions

XML description

Use self-describing XML for scripting, lowering barriers to entry
If you want to add a new tag/attribute, after defining and adding fields to the corresponding entity in the XSD, add a value in the AutoTestSuiteParser class.

Element reuse

Reference element files through ref tags

Ready to use, repeated references enable reuse

Extraction and comparison

Obtain the corresponding value by specifying the attribute of the html tag, and store the variableName in the map of threadLocal in the form of kv, so that it can be extracted with $variableName in the subsequent process of the same testFlow and compared with the expected value

Template matching click

Using JavaCV for template matching and click operations
e.g.:

Just use the attribute templateImgName
The template image is stored under src/test/template_img, and the source image is a screenshot of the current browser window
Tips: When using template matching, it is not recommended to execute it locally as it will most likely fail because local operations may interfere with the original positioning of the mouse.

Concurrency and distributed execution

By reading the configuration in the engine.properties file through reflection, the number of concurrent execution use cases can be dynamically configured.

During concurrent execution, tasks will be sent to selenium-hub and distributed to speed up execution.

Execute custom method

When using the custom tag, specify the bean name of the customFunction specified class, and the class should implement the execute method of ICustomAction

The method bean name is beanName in _@_Service()

Common operation encapsulation

Encapsulates commonly used operations and can be expanded at the same time

Environment deployment

selenium-grid

m1 (arm64)

version: "3"
services:
  selenium-hub:
    image: seleniarm/hub:4.0.0-beta-1-20210215
    container_name: selenium-hub-arm
    ports:
      - "4444:4444"
    environment:
      - GRID_MAX_SESSION=50
      - GRID_TIMEOUT=200
      - START_XVFB=false
      - GRID_CLEAN_UP_CYCLE=200
  chrome:
    image: seleniarm/node-chromium:4.0.0-beta-1-20210215
    volumes:
      -/dev/shm:/dev/shm
    depends_on:
      -selenium-hub
    environment:
      - SE_EVENT_BUS_PUBLISH_PORT=4444
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - NODE_MAX_INSTANCES=5
      -NODE_MAX_SESSION=5
      - GRID_CLEAN_UP_CYCLE=200

intel(x86)

version: "3"
services:
  selenium-hub:
    image: selenium/hub
    container_name: selenium-hub
    ports:
      - "4444:4444"
    environment:
      - GRID_MAX_SESSION=50
      - GRID_TIMEOUT=900
      - START_XVFB=false
  chrome:
    image: selenium/node-chrome
    volumes:
      -/dev/shm:/dev/shm
    depends_on:
      -selenium-hub
    environment:
      - SE_EVENT_BUS_PUBLISH_PORT=4444
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - NODE_MAX_INSTANCES=5
      -NODE_MAX_SESSION=5
      - GRID_CLEAN_UP_CYCLE=200

start.sh

#!/bin/sh

docker-compose up -d --scale chrome=2

chrome=2 represents the number of nodes in the selenium-grid cluster, chrome is the service name in docker-compose
Start the shell script, docker ps to check whether the startup is successful

Visit localhost:4444 / virtual machine ip:4444

Extentx

Create a Dockerfile

FROM node:alpine
LABEL maintainer="lain"

RUN mkdir -p ./app
WORKDIR ./app

RUN apk add --no-cache git
RUN git clone https://gist.github.com/3c4f35a41c58a55a0ffd00c3e64142c8.git tmpChange
RUN git clone https://github.com/anshooarora/extentx.git

RUN mv tmpChange/connections.js extentx/config/connections.js
RUN rm -rf tmpChange

WORKDIR ./extentx

EXPOSE 1337

RUN npm set registry https://registry.npm.taobao.org
RUN npm config set registry https://registry.npm.taobao.org
RUN npm config set disturl https://npm.taobao.org/dist
RUN npm install

CMD ["./node_modules/.bin/sails", "lift"]

Build image
docker build -t extentx .
Create docker-compose.yml file

version: '3.6'
services:
 extentx:
  build: .
  environment:
    - MONGODB_PORT_27017_TCP_ADDR=mongo
  links:
    -mongo:mongo
  ports:
    - 1337:1337

 mongo:
  image:mongo:3.4
  ports:
    - 27010:27017

docker-compose up -dStart
Just visit localhost:1337

Package to local warehouse

Download extentsReport-1.0-SNAPSHOT.jar attached to the project, extract the pom file in the jar package, place it in the same directory as the jar, and execute the command
mvn install:install-file -Dfile=extentsReport-1.0-SNAPSHOT.jar -DartifactId=extentsReport -DgroupId=com.antigenmhc -Dversion=1.0-SNAPSHOT -Dpackaging=jar -DpomFile=pom.xml
That’s it

JavaCV (taking arm64 as an example)

mac m1 (arm64)

The pre-environment is the downloaded arm64 version of JDK

  1. Install and set environment variables
# Upgrade brew
brew update
# Install cmake
brew install cmake
# Install ant
brew installant

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_331.jdk/Contents/Home
export PATH=$JAVA_HOME/bin:$PATH
export JAVA_AWT_INCLUDE_PATH=$JAVA_HOME
export JAVA_AWT_LIBRARY=$JAVA_HOME
export JAVA_INCLUDE_PATH=$JAVA_HOME/indclude
export JAVA_INCLUDE_PATH2=$JAVA_HOME/include/darwin
export JAVA_JVM_LIBRARY=$JAVA_HOME
  1. Open Java build

brew edit opencv
turn up
-DBUILD_opencv_java=OFF changed to -DBUILD_opencv_java=ON
Add the parameter after the above parameters: -DOPENCV_JAVA_TARGET_VERSION=1.8 to prevent compilation using a higher version of JDK

  1. compile

brew install --build-from-source opencv

  1. Generate jar and dylib: After success, libopencv_java470.dylib and opencv-470.jar will be generated in /opt/homebrew/Cellar/opencv/4.7.0/share/java/opencv4

Add jar and dylib to the project

Set the project JDK to the JDK just used for editing (i.e. JAVA\_HOME)
  1. Introduce dependencies
<dependency>
  <groupId>org.bytedeco</groupId>
  <artifactId>javacv-platform</artifactId>
  <version>1.5.7</version>
</dependency>
<dependency>
  <groupId>org.bytedeco</groupId>
  <artifactId>javacpp</artifactId>
  <version>1.5.7</version>
</dependency>
  1. run demo
//Picture to be matched
Mat src = imread("filePath",Imgcodecs.IMREAD_GRAYSCALE);
Mat mInput=src.clone();
// Get matching template
Mat mTemplate = imread("filePath",Imgcodecs.IMREAD_GRAYSCALE);
/**
* TM_SQDIFF = 0, squared difference matching method, the best match is 0, the larger the value, the worse the match.
* TM_SQDIFF_NORMED = 1, normalized squared difference matching method
* TM_CCORR = 2, correlation matching method, using multiplication operation, the larger the value, the better the match.
* TM_CCORR_NORMED = 3, normalized correlation matching method
* TM_CCOEFF = 4, correlation coefficient matching method, the best match is 1, -1 means the worst match
* TM_CCOEFF_NORMED = 5; Normalized correlation coefficient matching method
*/
int resultRows = mInput.rows() - mTemplate.rows() + 1;
int resultCols = mInput.cols() - mTemplate.cols() + 1;
Mat gResult = new Mat(resultRows, resultCols, CvType.CV_32FC1);

Imgproc.matchTemplate(mInput, mTemplate, gResult, Imgproc.TM_CCORR_NORMED);

Core.normalize(gResult, gResult, 0, 1, Core.NORM_MINMAX, -1, new Mat());
Core.MinMaxLocResult mmlr = Core.minMaxLoc(gResult);
Point matchLocation = mmlr.maxLoc;

double x = matchLocation.x + (mTemplate.cols() / 2);
double y = matchLocation.y + (mTemplate.rows() / 2);
System.out.println(new Point(x, y));

The console outputs the coordinates successfully.

Run the project

Project structure and description

The general structure of the project is as follows

qa-ui-test-demo
├─ screen: screenshot
├─ src
│ ├─ main
│ │ └─ resources
│ │ ├─ css
│ │ ├─ driver: browser driver
│ │ │ ├─ chromedriver
│ │ │ └─ geckodriver
│ │ ├─ cc.properties: Email sender’s email address
│ │ ├─ extentx.properties: connect extentx platform configuration
│ │ ├─ engine.properties: test report and core configuration
│ │ ├─ mail.properties: Mail configuration
│ │ └─ sendto.properties: Email of the email recipient
│ └─ test
│ ├─ java
│ │ └─ com
│ │ └─ qalain
│ │ └─ ui
│ │ └─ action: java script
│ └─ resources
│ ├─ page: page xml, used to convert to page pojo
│ │ └─ demo-baidu.xml
│ ├─ suiteflow: automated test process file
│ │ └─ demo-flow.xml
│ └─ suite-testng.xml
├─ pom.xml
└─ README.md

Because it has been encapsulated twice in xml, you need to understand common tags

  1. When action is openPage, the attribute that needs to be set is url;
  2. When the action is click, the attribute that needs to be set is refId;
  3. When action is fillvalue, the attributes that need to be set are elementId and value;
  4. When action is compareValue, the properties that need to be set are refId and expectValue;
  5. When action is keyBoardEnter, no other attributes need to be set;
  6. When action is swithWindow, there is no need to set other attributes;
  7. When the action is closeCurrentWindow, there is no need to set other properties;
  8. When action is closeDrive, no other attributes need to be set;
  9. When action is jsInvoker, the attribute that needs to be set is jsCode;
  10. When action is custom, the attribute that needs to be set is customFunction;
  11. When action is hover, there is no need to set other attributes

Finally: The following is the supporting learning materials. For friends who do [software testing], it should be the most comprehensive and complete preparation warehouse. This warehouse has also accompanied me through the most difficult journey. I hope it can also help you. ! [100% free without any tricks]

Software testing interview applet

A software test question bank that has been used by millions of people! ! ! Who is who knows! ! ! The most comprehensive interview test mini program on the Internet, you can use your mobile phone to answer questions, take the subway, bus, and roll it up!

Covering these interview question sections:

1. Basic theory of software testing, 2. web, app, interface function testing, 3. network, 4. database, 5. linux

6. Web, app, interface automation, 7. Performance testing, 8. Programming basics, 9. HR interview questions, 10. Open test questions, 11. Security testing, 12. Computer basics

How to obtain the full set of information: Click on the small card below to get it yourself