First: MySQL+MyBatis enables reading of test case data (interface automatic landing)

Explain how TestNG + MySQL + mybatis + extendreports can read test case data. The directories of all configuration files are released below for ease of understanding.

1. Configure mysql database

Here, take the logincase table as an example, and then take login as an explanation.

2. Configuration pom file
First, configure various dependencies of httpclient, mybatis, mysql, extentreports and testng in the pom file.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.course.code</groupId>
    <artifactId>userInfoTest</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>6</source>
                    <target>6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    
	<dependencies>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20170516</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.4</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>6.0.5</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.16</version>
        </dependency>
        <dependency>
            <groupId>com.relevantcodes</groupId>
            <artifactId>extentreports</artifactId>
            <version>2.41.1</version>
        </dependency>
        <dependency>
            <groupId>com.vimalselvam</groupId>
            <artifactId>testng-extentsreport</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.11</version>
        </dependency>
        <dependency>
            <groupId>com.aventstack</groupId>
            <artifactId>extentreports</artifactId>
            <version>3.0.6</version>
        </dependency>
    </dependencies>

3. Configure application Properties file
Configure application. In the resource directory Properties file to store the test address.

test.url=http://localhost:9529

#Login interface
login.uri=/v1/login

#Update user information
updateUserInfo.uri=/v1/updateUserInfo

#Get user list
getUserList.uri=/v1/getUserList

#Get user information
getUserInfo.uri=/v1/getUserInfo

#Add user interface
addUser.uri=/v1/addUser

4. Configure databaseconfig XML file
Configure databaseconfig. In the resource directory XML file to connect to the database.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <!-- Spatial naming of registered objects -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!-- Load data driver -->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!-- Database connection address -->
                <property name="url" value="jdbc:mysql://localhost:3306/myBatisTest"/>
                <!-- Database user, password -->
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <!-- Register mapping file:java Between object and database xml File path -->
    <mappers>
        <mapper resource="mapper/SQLMapper.xml"/>
    </mappers>
</configuration>

5. Configure TestNG XML file
Configure testng under the resource directory XML file to execute all testng test suites.

<?xml version="1.0" encoding="UTF-8" ?>
<suite name="User management system test suite">
    <test name="User management system test case">
        <classes>
            <class name="com.course.cases.loginTest">
                <methods>
                    <include name="loginTrue"/>
                    <include name="loginFalse"/>
                </methods>
            </class>

            <class name = "com.course.cases.AddUserTest">
                <methods>
                    <include name="addUser"/>
                </methods>
            </class>

            <class name = "com.course.cases.GetUserInfoTest">
                <methods>
                    <include name="getUserInfo"/>
                </methods>
            </class>

            <class name = "com.course.cases.GetUserListTest">
                <methods>
                    <include name="getUserList"/>
                </methods>
            </class>

            <class name = "com.course.cases.UpdateUserInfoTest">
                <methods>
                    <include name="updateUserInfo"/>
                    <include name="deleteUser"/>
                </methods>
            </class>
        </classes>
    </test>
    <listeners>
        <listener class-name="com.course.config.ExtentTestNGIReporterListener"></listener>
    </listeners>
</suite>

6. Configure sqlmapper XML file
In the resources/mapper directory, configure sqlmapper XML file, and the user stores the sql statements of all case s.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.course.model">
    <!--Get login interface case-->
    <select id="loginCase" parameterType="Integer" resultType="com.course.model.LoginCase">
        select * from loginCase
        where id=#{id};
    </select>

    <!--Add user interface case-->
    <select id="addUserCase" parameterType="Integer" resultType="com.course.model.AddUserCase">
        select * from addUserCase where id=#{id};
    </select>

    <!--Get user information case-->
    <select id="getUserInfoCase" parameterType="Integer" resultType="com.course.model.GetUserInfoCase">
        select * from getUserInfoCase where id=#{id};
    </select>

    <!--Get user list case-->
    <select id="getUserListCase" parameterType="Integer" resultType="com.course.model.GetUserListCase">
        select * from getUserListCase where id = #{id};
    </select>

    <!--to update/delete user case-->
    <select id="updateUserInfoCase" parameterType="Integer" resultType="com.course.model.UpdateUserInfoCase">
        select * from updateUserInfoCase where id = #{id};
    </select>
</mapper>

7. Configure model file
com. course. Under the model directory, configure the data configuration files of each interface and an InterfaceName enumeration.

Here, take the data in LoginCase as an example. The format of other cases is the same. Here, refer to the fields configured in mysql to declare one by one.

@Data
public class LoginCase {
    private int id;
    private String userName;
    private String password;
    private String expected;
}

InterfaceName is configured as follows

public enum InterfaceName {
    GETUSERLIST,LOGIN,UPDATEUSERINFO,GETUSERINFO,ADDUSER
}

8. config file
com. course. In the config directory, create a new extenstestngireporterlistener file and TestConfig file.
The extendtestngireporterlistener is the test report configuration file of extendreport, and the fixed code can be copied directly for use.

public class ExtentTestNGIReporterListener implements IReporter {
    //Generated path and file name
    private static final String OUTPUT_FOLDER = "test-output/";
    private static final String FILE_NAME = "index.html";

    private ExtentReports extent;

    @Override
    public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {
        init();
        boolean createSuiteNode = false;
        if(suites.size()>1){
            createSuiteNode=true;
        }
        for (ISuite suite : suites) {
            Map<String, ISuiteResult> result = suite.getResults();
            //If there are no use cases in suite, skip directly and do not generate them in the report
            if(result.size()==0){
                continue;
            }
            //Count the total number of successful, failed and skipped cases under suite
            int suiteFailSize=0;
            int suitePassSize=0;
            int suiteSkipSize=0;
            ExtentTest suiteTest=null;
            //When there are multiple suites, the test results of the same suite are classified into one category in the report to create a level-1 node.
            if(createSuiteNode){
                suiteTest = extent.createTest(suite.getName()).assignCategory(suite.getName());
            }
            boolean createSuiteResultNode = false;
            if(result.size()>1){
                createSuiteResultNode=true;
            }
            for (ISuiteResult r : result.values()) {
                ExtentTest resultNode;
                ITestContext context = r.getTestContext();
                if(createSuiteResultNode){
                    //If suite is not created, it will be created as a first level node in SuiteResult, otherwise it will be created as a child node of suite.
                    if( null == suiteTest){
                        resultNode = extent.createTest(r.getTestContext().getName());
                    }else{
                        resultNode = suiteTest.createNode(r.getTestContext().getName());
                    }
                }else{
                    resultNode = suiteTest;
                }
                if(resultNode != null){
                    resultNode.getModel().setName(suite.getName()+" : "+r.getTestContext().getName());
                    if(resultNode.getModel().hasCategory()){
                        resultNode.assignCategory(r.getTestContext().getName());
                    }else{
                        resultNode.assignCategory(suite.getName(),r.getTestContext().getName());
                    }
                    resultNode.getModel().setStartTime(r.getTestContext().getStartDate());
                    resultNode.getModel().setEndTime(r.getTestContext().getEndDate());
                    //Statistics of data under SuiteResult
                    int passSize = r.getTestContext().getPassedTests().size();
                    int failSize = r.getTestContext().getFailedTests().size();
                    int skipSize = r.getTestContext().getSkippedTests().size();
                    suitePassSize += passSize;
                    suiteFailSize += failSize;
                    suiteSkipSize += skipSize;
                    if(failSize>0){
                        resultNode.getModel().setStatus(Status.FAIL);
                    }
                    resultNode.getModel().setDescription(String.format("Pass: %s ; Fail: %s ; Skip: %s ;",passSize,failSize,skipSize));
                }
                buildTestNodes(resultNode,context.getFailedTests(), Status.FAIL);
                buildTestNodes(resultNode,context.getSkippedTests(), Status.SKIP);
                buildTestNodes(resultNode,context.getPassedTests(), Status.PASS);
            }
            if(suiteTest!= null){
                suiteTest.getModel().setDescription(String.format("Pass: %s ; Fail: %s ; Skip: %s ;",suitePassSize,suiteFailSize,suiteSkipSize));
                if(suiteFailSize>0){
                    suiteTest.getModel().setStatus(Status.FAIL);
                }
            }

        }
//        for (String s : Reporter.getOutput()) {
//            extent.setTestRunnerOutput(s);
//        }

        extent.flush();
    }

    private void init() {
        //If the folder does not exist, create it
        File reportDir= new File(OUTPUT_FOLDER);
        if(!reportDir.exists()&& !reportDir .isDirectory()){
            reportDir.mkdir();
        }
        ExtentHtmlReporter htmlReporter = new ExtentHtmlReporter(OUTPUT_FOLDER + FILE_NAME);
        // Set DNS for static files
        //How to solve CDN rawgit. Com
        htmlReporter.config().setResourceCDN(ResourceCDN.EXTENTREPORTS);

        htmlReporter.config().setDocumentTitle("api Automated test report");
        htmlReporter.config().setReportName("api Automated test report");
        htmlReporter.config().setChartVisibilityOnOpen(true);
        htmlReporter.config().setTestViewChartLocation(ChartLocation.TOP);
        htmlReporter.config().setTheme(Theme.STANDARD);
        htmlReporter.config().setCSS(".node.level-1  ul{ display:none;} .node.level-1.active ul{display:block;}");
        extent = new ExtentReports();
        extent.attachReporter(htmlReporter);
        extent.setReportUsesManualConfiguration(true);
    }

    private void buildTestNodes(ExtentTest extenttest, IResultMap tests, Status status) {
        //Gets the label of the parent node when the parent node exists
        String[] categories=new String[0];
        if(extenttest != null ){
            List<TestAttribute> categoryList = extenttest.getModel().getCategoryContext().getAll();
            categories = new String[categoryList.size()];
            for(int index=0;index<categoryList.size();index++){
                categories[index] = categoryList.get(index).getName();
            }
        }

        ExtentTest test;

        if (tests.size() > 0) {
            //Adjust the sorting of use cases by time
            Set<ITestResult> treeSet = new TreeSet<ITestResult>(new Comparator<ITestResult>() {
                @Override
                public int compare(ITestResult o1, ITestResult o2) {
                    return o1.getStartMillis()<o2.getStartMillis()?-1:1;
                }
            });
            treeSet.addAll(tests.getAllResults());
            for (ITestResult result : treeSet) {
                Object[] parameters = result.getParameters();
                String name="";
                //If there are parameters, the toString combination of parameters is used instead of the name in the report
                for(Object param:parameters){
                    name+=param.toString();
                }
                if(name.length()>0){
                    if(name.length()>50){
                        name= name.substring(0,49)+"...";
                    }
                }else{
                    name = result.getMethod().getMethodName();
                }
                if(extenttest==null){
                    test = extent.createTest(name);
                }else{
                    //When creating as a child node, the setting is consistent with the label of the parent node to facilitate report retrieval.
                    test = extenttest.createNode(name).assignCategory(categories);
                }
                //test.getModel().setDescription(description.toString());
                //test = extent.createTest(result.getMethod().getMethodName());
                for (String group : result.getMethod().getGroups())
                    test.assignCategory(group);

                List<String> outputList = Reporter.getOutput(result);
                for(String output:outputList){
                    //The log of the use case is output to the report
                    test.debug(output);
                }
                if (result.getThrowable() != null) {
                    test.log(status, result.getThrowable());
                }
                else {
                    test.log(status, "Test " + status.toString().toLowerCase() + "ed");
                }

                test.getModel().setStartTime(getTime(result.getStartMillis()));
                test.getModel().setEndTime(getTime(result.getEndMillis()));
            }
        }
    }

    private Date getTime(long millis) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(millis);
        return calendar.getTime();
    }
}

The url of each case and some variables to be used later are declared in TestConfig.

public class TestConfig {
    public static String loginUrl;
    public static String updateUserInfoUrl;
    public static String getUserListUrl;
    public static String getUserInfoUrl;
    public static String addUserUrl;

    public static DefaultHttpClient defaultHttpClient;
    public static CookieStore store;
}

9. Configure utils file
com. course. Configure the ConfigFile file and DatabaseUtil file in the utils directory.

Assign the url of each case in ConfigFile

public class ConfigFile {
    public static ResourceBundle bundle = ResourceBundle.getBundle("application",Locale.CHINA);
    public static String getUrl(InterfaceName name){
        String address = bundle.getString("test.url");
        String uri = "";
        //Final test address
        String testUrl;

        if (name == InterfaceName.GETUSERLIST){
            uri = bundle.getString("getUserList.uri");
        }
        if (name == InterfaceName.LOGIN){
            uri = bundle.getString("login.uri");
        }
        if (name == InterfaceName.UPDATEUSERINFO){
            uri = bundle.getString("updateUserInfo.uri");
        }
        if (name == InterfaceName.GETUSERINFO){
            uri = bundle.getString("getUserInfo.uri");
        }
        if (name == InterfaceName.ADDUSER){
            uri = bundle.getString("addUser.uri");
        }
        testUrl = address + uri;

        return testUrl;
    }

}

A getSqlsession method is configured in DatabaseUtil to execute the sql statements in the configuration file so that each case can be called directly instead of writing this part of code repeatedly.

public class DatabaseUtil {
    public static SqlSession getSqlsession() throws IOException {

        //Get configuration resource file
        Reader reader = Resources.getResourceAsReader("databaseConfig.xml");

        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
        //sqlSession is the ability to execute sql statements in the configuration file
        SqlSession sqlSession=factory.openSession();
        return sqlSession;
    }
}

10. Configure cases file
com. course. Configure all case classes in the cases directory
Here we only take loginTest as an example

public class loginTest {

    @BeforeTest(groups="loginTrue",description = "Test preparation, obtaining httpClient object")
    public void beforeTest(){
        TestConfig.getUserInfoUrl = ConfigFile.getUrl(InterfaceName.GETUSERINFO);
        TestConfig.getUserListUrl = ConfigFile.getUrl(InterfaceName.GETUSERLIST);
        TestConfig.addUserUrl = ConfigFile.getUrl(InterfaceName.ADDUSER);
        TestConfig.loginUrl = ConfigFile.getUrl(InterfaceName.LOGIN);
        TestConfig.updateUserInfoUrl = ConfigFile.getUrl(InterfaceName.UPDATEUSERINFO);

        TestConfig.defaultHttpClient = new DefaultHttpClient();
    }

    @Test(groups = "loginTrue",description = "User login interface test")
    public void loginTrue() throws IOException {
        SqlSession session = DatabaseUtil.getSqlsession();
        LoginCase loginCase = session.selectOne("loginCase",1);
        System.out.println(loginCase.toString());
        System.out.println(TestConfig.loginUrl);
    }


    @Test(description = "User login failure interface test")
    public void loginFalse() throws IOException {
        SqlSession session = DatabaseUtil.getSqlsession();
        LoginCase loginCase = session.selectOne("loginCase",2);
        System.out.println(loginCase.toString());
        System.out.println(TestConfig.loginUrl);
    }
}

Here, a complete set of test case data read from mysql to the configuration stored in the java project is completed
We can execute TestNG XML file, you can see that all cases are executed successfully, and all data information and the url of each case are printed on the console.

Finally, check the index. Output directory in the test output directory XML file, open it with a browser, and you can see that the result of extensreport is also generated successfully.

Keywords: MySQL

Added by niekos on Wed, 05 Jan 2022 08:08:35 +0200