【七:(测试用例)spring boot+testng+xml+mock实现用例管理+数据校验】

目录

1、目录结构的相关类

cases类

1、添加用户 AddUserTest

java 复制代码
import com.tester.config.TestConfig;
import com.tester.model.AddUserCase;
import com.tester.model.User;
import com.tester.utils.DatabaseUtil;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.apache.ibatis.session.SqlSession;
import org.json.JSONObject;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.io.IOException;

public class AddUserTest {
    //需要依赖loginTrue的分组的用例
    @Test(dependsOnGroups = "loginTrue",description = "添加用户接口接口")
    public void addUser() throws IOException, InterruptedException {
        SqlSession session = DatabaseUtil.getSqlSession();
        AddUserCase addUserCase = session.selectOne("addUserCase",1);
        System.out.println("addUserCase"+addUserCase.toString());
        System.out.println("addUserUrl"+TestConfig.addUserUrl);

        /**
        //下边的代码为写完接口的测试代码
        String result = getResult(addUserCase);

        //查询用户看是否添加成功
        Thread.sleep(2000);
        User user = session.selectOne("addUser",addUserCase);
        System.out.println(user.toString());

        //处理结果,就是判断返回结果是否符合预期
        Assert.assertEquals(addUserCase.getExpected(),result);
         */

    }

    private String getResult(AddUserCase addUserCase) throws IOException {
        //下边的代码为写完接口的测试代码
        HttpPost post = new HttpPost(TestConfig.addUserUrl);
        JSONObject param = new JSONObject();
        param.put("userName",addUserCase.getUserName());
        param.put("password",addUserCase.getPassword());
        param.put("sex",addUserCase.getSex());
        param.put("age",addUserCase.getAge());
        param.put("permission",addUserCase.getPermission());
        param.put("isDelete",addUserCase.getIsDelete());
        //设置请求头信息 设置header
        post.setHeader("content-type","application/json");
        //将参数信息添加到方法中
        StringEntity entity = new StringEntity(param.toString(),"utf-8");
        post.setEntity(entity);
        //设置cookies
        TestConfig.defaultHttpClient.setCookieStore(TestConfig.store);
        //声明一个对象来进行响应结果的存储
        String result;
        //执行post方法
        HttpResponse response = TestConfig.defaultHttpClient.execute(post);
        //获取响应结果
        result = EntityUtils.toString(response.getEntity(),"utf-8");
        System.out.println(result);
        return result;
    }

}

2、获取用户列表信息 GetUserInfoListTest

java 复制代码
import com.tester.config.TestConfig;
import com.tester.model.GetUserListCase;
import com.tester.model.User;
import com.tester.utils.DatabaseUtil;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.apache.ibatis.session.SqlSession;
import org.json.JSONArray;
import org.json.JSONObject;
import org.testng.Assert;
import org.testng.annotations.Test;

import java.io.IOException;
import java.util.List;

public class GetUserInfoListTest {

    @Test(dependsOnGroups="loginTrue",description = "获取性别为男的用户信息")
    public void getUserListInfo() throws IOException, InterruptedException {

        SqlSession session = DatabaseUtil.getSqlSession();
        GetUserListCase getUserListCase = session.selectOne("getUserListCase",1);
        System.out.println(getUserListCase.toString());
        System.out.println(TestConfig.getUserListUrl);

        /**
        //下边为写完接口的代码  发送请求获取结果
        JSONArray resultJson = getJsonResult(getUserListCase);

        Thread.sleep(2000);
        List<User> userList = session.selectList(getUserListCase.getExpected(),getUserListCase);
        for(User u : userList){
            System.out.println("list获取的user:"+u.toString());
        }
        JSONArray userListJson = new JSONArray(userList);

        Assert.assertEquals(userListJson.length(),resultJson.length());
        for(int i = 0;i<resultJson.length();i++){
            JSONObject expect = (JSONObject) resultJson.get(i);
            JSONObject actual = (JSONObject) userListJson.get(i);
            Assert.assertEquals(expect.toString(), actual.toString());
        }
         */


    }

    private JSONArray getJsonResult(GetUserListCase getUserListCase) throws IOException {
        HttpPost post = new HttpPost(TestConfig.getUserListUrl);
        JSONObject param = new JSONObject();
        param.put("userName",getUserListCase.getUserName());
        param.put("sex",getUserListCase.getSex());
        param.put("age",getUserListCase.getAge());
        //设置请求头信息 设置header
        post.setHeader("content-type","application/json");
        //将参数信息添加到方法中
        StringEntity entity = new StringEntity(param.toString(),"utf-8");
        post.setEntity(entity);
        //设置cookies
        TestConfig.defaultHttpClient.setCookieStore(TestConfig.store);
        //声明一个对象来进行响应结果的存储
        String result;
        //执行post方法
        HttpResponse response = TestConfig.defaultHttpClient.execute(post);
        //获取响应结果
        result = EntityUtils.toString(response.getEntity(),"utf-8");
        JSONArray jsonArray = new JSONArray(result);

        System.out.println("调用接口list result:"+result);

        return jsonArray;

    }

}

3、获取用户信息 GetUserInfoTest

java 复制代码
import com.tester.config.TestConfig;
import com.tester.model.GetUserInfoCase;
import com.tester.model.User;
import com.tester.utils.DatabaseUtil;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.apache.ibatis.session.SqlSession;
import org.json.JSONArray;
import org.json.JSONObject;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class GetUserInfoTest {


    @Test(dependsOnGroups="loginTrue",description = "获取userId为1的用户信息")
    public void getUserInfo() throws IOException, InterruptedException {
        SqlSession session = DatabaseUtil.getSqlSession();
        GetUserInfoCase getUserInfoCase = session.selectOne("getUserInfoCase",1);
        System.out.println(getUserInfoCase.toString());
        System.out.println(TestConfig.getUserInfoUrl);

        /**
        //下边为写完接口的代码
        JSONArray resultJson = getJsonResult(getUserInfoCase);


        Thread.sleep(2000);
        User user = session.selectOne(getUserInfoCase.getExpected(),getUserInfoCase);
        System.out.println("自己查库获取用户信息:"+user.toString());

        List userList = new ArrayList();
        userList.add(user);
        JSONArray jsonArray = new JSONArray(userList);
        System.out.println("获取用户信息:"+jsonArray.toString());
        System.out.println("调用接口获取用户信息:"+resultJson.toString());
        Assert.assertEquals(jsonArray,resultJson);
        */
    }


    private JSONArray getJsonResult(GetUserInfoCase getUserInfoCase) throws IOException {
        HttpPost post = new HttpPost(TestConfig.getUserInfoUrl);
        JSONObject param = new JSONObject();
        param.put("id",getUserInfoCase.getUserId());
        //设置请求头信息 设置header
        post.setHeader("content-type","application/json");
        //将参数信息添加到方法中
        StringEntity entity = new StringEntity(param.toString(),"utf-8");
        post.setEntity(entity);
        //设置cookies
        TestConfig.defaultHttpClient.setCookieStore(TestConfig.store);
        //声明一个对象来进行响应结果的存储
        String result;
        //执行post方法
        HttpResponse response = TestConfig.defaultHttpClient.execute(post);
        //获取响应结果
        result = EntityUtils.toString(response.getEntity(),"utf-8");
        System.out.println("调用接口result:"+result);
        List resultList = Arrays.asList(result);
        JSONArray array = new JSONArray(resultList);
        System.out.println(array.toString());
        return array;

    }
}

4、登录测试

java 复制代码
import com.tester.model.InterfaceName;
import com.tester.config.TestConfig;
import com.tester.model.LoginCase;
import com.tester.utils.ConfigFile;
import com.tester.utils.DatabaseUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.ibatis.session.SqlSession;
import org.json.JSONObject;
import org.testng.Assert;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

import java.io.IOException;

public class LoginTest {


    @BeforeTest(groups = "loginTrue",description = "测试准备工作,获取HttpClient对象")
    public void beforeTest(){
        //声明http客户端
        TestConfig.defaultHttpClient = new DefaultHttpClient();

        TestConfig.getUserInfoUrl = ConfigFile.getUrl(InterfaceName.GETUSERINFO);
        TestConfig.getUserListUrl = ConfigFile.getUrl(InterfaceName.GETUSERLIST);
        TestConfig.loginUrl = ConfigFile.getUrl(InterfaceName.LOGIN);
        TestConfig.updateUserInfoUrl = ConfigFile.getUrl(InterfaceName.UPDATEUSERINFO);
        TestConfig.addUserUrl = ConfigFile.getUrl(InterfaceName.ADDUSERINFO);
    }


    @Test(groups = "loginTrue",description = "用户成功登陆接口")
    public void loginTrue() throws IOException {
        //查询数据
        SqlSession session = DatabaseUtil.getSqlSession();
        LoginCase loginCase = session.selectOne("loginCase",1);
        //System.out.println("数据库数据:"+loginCase.toString());

        //验证输出url
        System.out.println("访问的url:"+TestConfig.loginUrl);

        //发起http://localhost:8889/login请求,获取结果
        String result = getResult(loginCase);

        //处理结果,就是判断返回结果是否符合预期    getExpected=逾期结果   result=实际结果
        Assert.assertEquals(loginCase.getExpected(),result);
        System.out.println("预期结果:"+loginCase.getExpected()+"\n"+"实际结果:"+result);



    }

    @Test(description = "用户登陆失败接口")
    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);

        /**
        //下边的代码为写完接口的测试代码
        String result = getResult(loginCase);
        //处理结果,就是判断返回结果是否符合预期
        Assert.assertEquals(loginCase.getExpected(),result);
         */

    }



    //登录用户
    private String getResult(LoginCase loginCase) throws IOException {
        //声明一个对象来进行响应结果的存储
        String result;

        //下边的代码为写完接口的测试代码
        HttpPost post = new HttpPost(TestConfig.loginUrl);
        JSONObject param = new JSONObject();
        param.put("userName",loginCase.getUserName());
        param.put("password",loginCase.getPassword());
        //设置请求头信息 设置header
        post.setHeader("content-type","application/json");

        //将参数信息添加到方法中
        StringEntity entity = new StringEntity(param.toString(),"utf-8");
        post.setEntity(entity);

        //执行post方法
        HttpResponse response = TestConfig.defaultHttpClient.execute(post);
        //获取响应结果
        result = EntityUtils.toString(response.getEntity(),"utf-8");

        //储存cookies信息
        TestConfig.store = TestConfig.defaultHttpClient.getCookieStore();
        return result;
    }

}

5、更新用户信息

java 复制代码
import com.tester.config.TestConfig;
import com.tester.model.UpdateUserInfoCase;
import com.tester.model.User;
import com.tester.utils.DatabaseUtil;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.apache.ibatis.session.SqlSession;
import org.json.JSONObject;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.io.IOException;

public class UpdateUserInfoTest {

    @Test(dependsOnGroups = "loginTrue",description = "更改用户信息")
    public void updateUserInfo() throws IOException, InterruptedException {
        SqlSession session = DatabaseUtil.getSqlSession();
        UpdateUserInfoCase updateUserInfoCase = session.selectOne("updateUserInfoCase",1);
        System.out.println(updateUserInfoCase.toString());
        System.out.println(TestConfig.updateUserInfoUrl);

/**
        //下边为写完接口的代码
        int result = getResult(updateUserInfoCase);

        //获取更新后的结果
        Thread.sleep(2000);
        User user = session.selectOne(updateUserInfoCase.getExpected(),updateUserInfoCase);
        System.out.println(user.toString());

        Assert.assertNotNull(user);
        Assert.assertNotNull(result);
 */

    }

    @Test(dependsOnGroups = "loginTrue",description = "删除用户")
    public void deleteUser() throws IOException, InterruptedException {
        SqlSession session = DatabaseUtil.getSqlSession();
        UpdateUserInfoCase updateUserInfoCase = session.selectOne("updateUserInfoCase",2);
        System.out.println(updateUserInfoCase.toString());
        System.out.println(TestConfig.updateUserInfoUrl);

        /**
        //下边为写完接口的代码
        int result = getResult(updateUserInfoCase);

        Thread.sleep(2000);
        User user = session.selectOne(updateUserInfoCase.getExpected(),updateUserInfoCase);
        System.out.println(user.toString());

        Assert.assertNotNull(user);
        Assert.assertNotNull(result);
         */
    }


    private int getResult(UpdateUserInfoCase updateUserInfoCase) throws IOException {
        HttpPost post = new HttpPost(TestConfig.updateUserInfoUrl);
        JSONObject param = new JSONObject();
        param.put("id",updateUserInfoCase.getUserId());
        param.put("userName",updateUserInfoCase.getUserName());
        param.put("sex",updateUserInfoCase.getSex());
        param.put("age",updateUserInfoCase.getAge());
        param.put("permission",updateUserInfoCase.getPermission());
        param.put("isDelete",updateUserInfoCase.getIsDelete());
        //设置请求头信息 设置header
        post.setHeader("content-type","application/json");
        //将参数信息添加到方法中
        StringEntity entity = new StringEntity(param.toString(),"utf-8");
        post.setEntity(entity);
        //设置cookies
        TestConfig.defaultHttpClient.setCookieStore(TestConfig.store);
        //声明一个对象来进行响应结果的存储
        String result;
        //执行post方法
        HttpResponse response = TestConfig.defaultHttpClient.execute(post);
        //获取响应结果
        result = EntityUtils.toString(response.getEntity(),"utf-8");
        System.out.println(result);
        return Integer.parseInt(result);

    }

}

config类

1、报告配置

java 复制代码
public class ExtentTestNGIReporterListener implements IReporter {
    //生成的路径以及文件名
    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();
            //如果suite里面没有任何用例,直接跳过,不在报告里生成
            if(result.size()==0){
                continue;
            }
            //统计suite下的成功、失败、跳过的总用例数
            int suiteFailSize=0;
            int suitePassSize=0;
            int suiteSkipSize=0;
            ExtentTest suiteTest=null;
            //存在多个suite的情况下,在报告中将同一个一个suite的测试结果归为一类,创建一级节点。
            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){
                    //没有创建suite的情况下,将在SuiteResult的创建为一级节点,否则创建为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());
                    //统计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() {
        //文件夹不存在的话进行创建
        File reportDir= new File(OUTPUT_FOLDER);
        if(!reportDir.exists()&& !reportDir .isDirectory()){
            reportDir.mkdir();
        }
        ExtentHtmlReporter htmlReporter = new ExtentHtmlReporter(OUTPUT_FOLDER + FILE_NAME);
        // 设置静态文件的DNS
        //怎么样解决cdn.rawgit.com访问不了的情况
        htmlReporter.config().setResourceCDN(ResourceCDN.EXTENTREPORTS);

        htmlReporter.config().setDocumentTitle("api自动化测试报告");
        htmlReporter.config().setReportName("api自动化测试报告");
        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) {
        //存在父节点时,获取父节点的标签
        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) {
            //调整用例排序,按时间排序
            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="";
                //如果有参数,则使用参数的toString组合代替报告中的name
                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{
                    //作为子节点进行创建时,设置同父节点的标签一致,便于报告检索。
                    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){
                    //将用例的log输出报告中
                    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();
    }
}

2、用户路径配置

java 复制代码
import lombok.Data;
import org.apache.http.client.CookieStore;
import org.apache.http.impl.client.DefaultHttpClient;

/**
 * 将从工具里面获取的地址赋值到 这里面,,,
 *
 */
@Data
public class TestConfig {

    //登陆接口uri
    public static String loginUrl;

    //更新用户信息接口uri
    public static String updateUserInfoUrl;

    //获取用户列表接口uri
    public static String getUserListUrl;

    //获取用户信息接口uri
    public static String getUserInfoUrl;

    //添加用户信息接口
    public static String addUserUrl;

    //用来存储cookies信息的变量
    public static CookieStore store;

    //声明http客户端
    public static DefaultHttpClient defaultHttpClient;

}

model类

java 复制代码
import lombok.Data;

@Data
public class AddUserCase {
    private int id;
    private String userName;
    private String password;
    private String sex;
    private String age;
    private String permission;
    private String isDelete;
    private String expected;
}
java 复制代码
@Data
public class GetUserInfoCase {
    private  int id;
    private int userId;
    private String expected;
}
java 复制代码
@Data
public class GetUserListCase {
    private String userName;
    private String age;
    private String sex;
    private String expected;
}
java 复制代码
public enum InterfaceName {
    GETUSERLIST,
    LOGIN,
    UPDATEUSERINFO,
    GETUSERINFO,
    ADDUSERINFO
}
java 复制代码
@Data
public class LoginCase {
        private int id;
        private String userName;
        private String password;
        private String expected;
}
java 复制代码
@Data
public class UpdateUserInfoCase {
    private int id;
    private int userId;
    private String userName;
    private String sex;
    private String age;
    private String permission;
    private String isDelete;
    private String expected;
}
java 复制代码
import lombok.Data;
@Data
public class User {
        private int id;
        private String userName;
        private String password;
        private String age;
        private String sex;
        private String permission;
        private String isDelete;

        @Override
        public String toString(){
              return (
              "id:"+id+","+
              "userName:"+userName+","+
              "password:"+password+","+
              "age:"+age+","+
              "sex:"+sex+","+
              "permission:"+permission+","+
              "isDelete:"+isDelete+"}"
              );
        }
}

utils类

java 复制代码
import com.tester.model.InterfaceName;
import java.util.Locale;
import java.util.ResourceBundle;

public class ConfigFile {

   private static ResourceBundle bundle= ResourceBundle.getBundle("application", Locale.CHINA);;

    public static String getUrl(InterfaceName name){
        //主地址
        String address = bundle.getString("test.url");
        String uri = "";
        //最终的测试地址
        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.ADDUSERINFO){
            uri = bundle.getString("addUser.uri");
        }
        //最终拼接的地址
        testUrl = address + uri;
        return testUrl;
    }
}
java 复制代码
public class DatabaseUtil {

    public static SqlSession getSqlSession() throws IOException {
        //获取配置的资源文件
        Reader reader = Resources.getResourceAsReader("databaseConfig.xml");
        //得到SqlSessionFactory,使用类加载器加载xml文件
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
        //得到sqlsession对象,这个对象就能执行配置文件中的sql语句啦
        SqlSession session = factory.openSession();
        return session;
    }
}

模板--页面模板内容自己可以去百度找

java 复制代码
package com.tester.utils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.testng.*;
import org.testng.xml.XmlSuite;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;


public class TestReport implements IReporter {
    private long currentTime = System.currentTimeMillis();
    private SimpleDateFormat formatter = new SimpleDateFormat ("yyyy年-MM月-dd日-HH时mm分ss秒");
    private Date date = new Date(currentTime);
    private String reportdate = formatter.format(date);
    // 定义生成测试报告的路径和文件名,为兼容Windows和Linux此处使用File.separator代替分隔符
    private String path = System.getProperty("user.dir")+File.separator+reportdate+".html";
    // 定义html样式模板所在路径
    private String templatePath = System.getProperty("user.dir")+File.separator+"template";

    private int testsPass = 0;

    private int testsFail = 0;

    private int testsSkip = 0;

    private String beginTime;

    private long totalTime;

    private String name = "PaaS平台自动化测试";
    /**
     public TestReport(){
     long currentTime = System.currentTimeMillis();
     SimpleDateFormat formatter = new SimpleDateFormat ("yyyy年-MM月-dd日-HH时mm分ss秒");
     Date date = new Date(currentTime);
     name = formatter.format(date);
     }

     public TestReport(String name){
     this.name = name;
     if(this.name==null){
     long currentTime = System.currentTimeMillis();
     SimpleDateFormat formatter = new SimpleDateFormat ("yyyy年-MM月-dd日-HH时mm分ss秒");
     Date date = new Date(currentTime);
     this.name = formatter.format(date);
     }
     }
     */
    @Override
    public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {
        List<ITestResult> list = new ArrayList<ITestResult>();
        for (ISuite suite : suites) {
            Map<String, ISuiteResult> suiteResults = suite.getResults();
            for (ISuiteResult suiteResult : suiteResults.values()) {
                ITestContext testContext = suiteResult.getTestContext();
                IResultMap passedTests = testContext.getPassedTests();
                testsPass = testsPass + passedTests.size();
                IResultMap failedTests = testContext.getFailedTests();
                testsFail = testsFail + failedTests.size();
                IResultMap skippedTests = testContext.getSkippedTests();
                testsSkip = testsSkip + skippedTests.size();
                IResultMap failedConfig = testContext.getFailedConfigurations();
                list.addAll(this.listTestResult(passedTests));
                list.addAll(this.listTestResult(failedTests));
                list.addAll(this.listTestResult(skippedTests));
                list.addAll(this.listTestResult(failedConfig));
            }
        }
        this.sort(list);
        this.outputResult(list);
    }

    private ArrayList<ITestResult> listTestResult(IResultMap resultMap) {
        Set<ITestResult> results = resultMap.getAllResults();
        return new ArrayList<ITestResult>(results);
    }

    private void sort(List<ITestResult> list) {
        Collections.sort(list, new Comparator<ITestResult>() {
            @Override
            public int compare(ITestResult r1, ITestResult r2) {
                if (r1.getStartMillis() > r2.getStartMillis()) {
                    return 1;
                } else {
                    return -1;
                }
            }
        });
    }

    private void outputResult(List<ITestResult> list) {
        try {
            List<ReportInfo> listInfo = new ArrayList<ReportInfo>();
            int index = 0;
            for (ITestResult result : list) {
                String tn = result.getTestContext().getCurrentXmlTest().getParameter("testCase");
                if(index==0){
                    SimpleDateFormat formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
                    beginTime = formatter.format(new Date(result.getStartMillis()));
                    index++;
                }
                long spendTime = result.getEndMillis() - result.getStartMillis();
                totalTime += spendTime;
                String status = this.getStatus(result.getStatus());
                List<String> log = Reporter.getOutput(result);
                for (int i = 0; i < log.size(); i++) {
                    log.set(i, log.get(i).replaceAll("\"", "\\\\\""));
                }
                Throwable throwable = result.getThrowable();
                if(throwable!=null){
                    log.add(throwable.toString().replaceAll("\"", "\\\\\""));
                    StackTraceElement[] st = throwable.getStackTrace();
                    for (StackTraceElement stackTraceElement : st) {
                        log.add(("    " + stackTraceElement).replaceAll("\"", "\\\\\""));
                    }
                }
                ReportInfo info = new ReportInfo();
                info.setName(tn);
                info.setSpendTime(spendTime+"ms");
                info.setStatus(status);
                info.setClassName(result.getInstanceName());
                info.setMethodName(result.getName());
                info.setDescription(result.getMethod().getDescription());
                info.setLog(log);
                listInfo.add(info);
            }
            Map<String, Object> result = new HashMap<String, Object>();
            result.put("testName", name);
            result.put("testPass", testsPass);
            result.put("testFail", testsFail);
            result.put("testSkip", testsSkip);
            result.put("testAll", testsPass+testsFail+testsSkip);
            result.put("beginTime", beginTime);
            result.put("totalTime", totalTime+"ms");
            result.put("testResult", listInfo);
            Gson gson = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create();
            String template = this.read(templatePath);
            BufferedWriter output = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(new File(path)),"UTF-8"));
            template = template.replaceFirst("\\$\\{resultData\\}", Matcher.quoteReplacement(gson.toJson(result)));
            output.write(template);
            output.flush();
            output.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private String getStatus(int status) {
        String statusString = null;
        switch (status) {
            case 1:
                statusString = "成功";
                break;
            case 2:
                statusString = "失败";
                break;
            case 3:
                statusString = "跳过";
                break;
            default:
                break;
        }
        return statusString;
    }

    public static class ReportInfo {

        private String name;

        private String className;

        private String methodName;

        private String description;

        private String spendTime;

        private String status;

        private List<String> log;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getClassName() {
            return className;
        }

        public void setClassName(String className) {
            this.className = className;
        }

        public String getMethodName() {
            return methodName;
        }

        public void setMethodName(String methodName) {
            this.methodName = methodName;
        }

        public String getSpendTime() {
            return spendTime;
        }

        public void setSpendTime(String spendTime) {
            this.spendTime = spendTime;
        }

        public String getStatus() {
            return status;
        }

        public void setStatus(String status) {
            this.status = status;
        }

        public List<String> getLog() {
            return log;
        }

        public void setLog(List<String> log) {
            this.log = log;
        }

        public String getDescription() {
            return description;
        }

        public void setDescription(String description) {
            this.description = description;
        }

    }

    private String read(String path) {
        File file = new File(path);
        InputStream is = null;
        StringBuffer sb = new StringBuffer();
        try {
            is = new FileInputStream(file);
            int index = 0;
            byte[] b = new byte[1024];
            while ((index = is.read(b)) != -1) {
                sb.append(new String(b, 0, index));
            }
            return sb.toString();
        } catch (FileNotFoundException e) {

            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

配置配置类

SQLMapper.xml

java 复制代码
<?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,如果有多个mapper文件,这个必须唯一 -->
<mapper namespace="com.tester.model">
    <!--获取登陆接口case-->
    <select id="loginCase" parameterType="Integer"  resultType="com.tester.model.LoginCase">
        select * from loginCase
        where id = #{id};
    </select>
    <!--添加用户接口case-->
    <select id="addUserCase" parameterType="Integer" resultType="com.tester.model.AddUserCase">
        select * from addUserCase where id=#{id};
    </select>

    <!--获取用户信息case-->
    <select id="getUserInfoCase" parameterType="Integer" resultType="com.tester.model.GetUserInfoCase">
        <!-- SQL语句 -->
        select * from getUserInfoCase where id=#{id};
    </select>

    <!--获取用户列表case-->
    <select id="getUserListCase" parameterType="Integer" resultType="com.tester.model.GetUserListCase">
        <!-- SQL语句 -->
        select * from getUserListCase where id=#{id};
    </select>

    <!--更新/删除用户信息case-->
    <select id="updateUserInfoCase" parameterType="Integer" resultType="com.tester.model.UpdateUserInfoCase">
        select * from updateUserInfoCase where id = #{id};
    </select>


    <!--添加用户接口-->
    <select id="addUser" parameterType="com.tester.model.AddUserCase" resultType="com.tester.model.User">
        select * from user where
        userName=#{userName}
        and password=#{password}
        and sex=#{sex}
        and age=#{age}
        and permission=#{permission}
        and isDelete=#{isDelete};
    </select>

    <!--获取用户信息-->
    <select id="getUserInfo" parameterType="com.tester.model.GetUserInfoCase" resultType="com.tester.model.User">
        <!-- SQL语句 -->
        select * from user where
        id=#{userId};
    </select>

    <!--获取用户列表-->
    <select id="getUserList" parameterType="com.tester.model.GetUserListCase" resultType="com.tester.model.User">
        <!-- SQL语句 -->
        select * from user
        <trim prefix="WHERE" prefixOverrides="and">
            <if test="null != userName and '' !=userName">
                AND userName=#{userName}
            </if>
            <if test="null != sex and '' !=sex">
                AND sex=#{sex}
            </if>
            <if test="null != age and '' !=age">
                AND age=#{age}
            </if>

        </trim>
        ;
    </select>

    <!--获取更新后的数据-->
    <select id="getUpdateUserInfo" parameterType="com.tester.model.UpdateUserInfoCase" resultType="com.tester.model.User">
        select * from user
        <trim prefix="WHERE" prefixOverrides="and">
            <if test="null != userName and '' !=userName">
                AND userName=#{userName}
            </if>
            <if test="null != sex and '' !=sex">
                AND sex=#{sex}
            </if>
            <if test="null != age and '' !=age">
                AND age=#{age}
            </if>
            <if test="null != permission and '' !=permission">
                AND permission=#{permission}
            </if>
            <if test="null != isDelete and '' !=isDelete">
                AND isDelete=#{isDelete}
            </if>
        </trim>
       And id = #{userId};
    </select>
</mapper>

spring boot全局配置

java 复制代码
test.url=http://localhost:8888

#登陆接口uri
login.uri=/login

#更新用户信息接口uri
updateUserInfo.uri=/updateUserInfo

#获取用户列表接口uri
getUserList.uri=/getUserListInfo

#获取用户信息接口uri
getUserInfo.uri=/getUserInfo

#添加用户接口uri
addUser.uri=/addUser

databaseConfig.xml

java 复制代码
<?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>
    <!-- 注册对象的空间命名 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!-- 1.加载数据库驱动 -->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!-- 2.数据库连接地址 -->
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/course"/>
                <!-- 数据库用户... -->
                <property name="username" value="root"/>
                <!-- 数据库密码... -->
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 注册映射文件:java对象与数据库之间的xml文件路径! -->
<mappers>
    <mapper resource="mapper/SQLMapper.xml"/>
</mappers>
</configuration>

testng.xml配置

java 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<suite name="用户管理系统测试套件">
    <test name="用户管理系统测试用例">
        <classes>
            <class name="com.tester.cases.LoginTest">
                <methods>
                    <include name="loginTrue"/>
                    <include name="loginFalse"/>
                </methods>
            </class>

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

            <class name="com.tester.cases.GetUserInfoTest">
                <methods>
                    <include name="getUserInfo"/>
                </methods>
            </class>
            <class name="com.tester.cases.UpdateUserInfoTest">
                <methods>
                    <include name="updateUserInfo"/>
                    <include name="deleteUser"/>
                </methods>
            </class>

            <class name="com.tester.cases.GetUserInfoListTest">
                <methods>
                    <include name="getUserListInfo"/>
                </methods>
            </class>
        </classes>

    </test>

    <listeners>
        <listener class-name="com.tester.config.ExtentTestNGIReporterListener" />
    </listeners>

</suite>

测试

1、前提条件

第一步:首先mock数据

[
  {
    "description":"登陆接口,成功后返回cookies",
    "request":{
      "uri":"/login",
      "method":"post",
      "json":{
        "userName":"abc",
        "password":"123"
      }
    },
    "response":{
      "cookies":{
        "login":"true"
      },
      "text":"true"
    }
  },
  {
    "description":"获取用户信息",
    "request":{
      "uri":"/getUserInfo",
      "method":"post",
      "json":{
        "userId":"1"
      },
      "cookies":{
        "login":"true"
      }
    },
    "response":{
      "json":{
        "id":"1",
        "userName":"zhangsan",
        "password":"123456",
        "age":"20",
        "sex":"0",
        "permission":"0",
        "isDelete":"0"
      }
    }
  },
  {
    "description":"获取用户信息接口",
    "request":{
      "uri":"/getUserListInfo",
      "method":"post",
      "json":{
        "sex":"0"
      },
      "cookies":{
        "login":"true"
      }
    },
    "response":{
      "json":[
        {
        "id":"1",
        "userName":"zhangsan",
        "password":"123456",
        "age":"20",
        "sex":"0",
        "permission":"0",
        "isDelete":"0"
      },
        {
          "id":"3",
          "userName":"wangwu",
          "password":"123456",
          "age":"30",
          "sex":"0",
          "permission":"1",
          "isDelete":"0"
        },{
          "id":"5",
          "userName":"zhang1",
          "password":"123",
          "age":"20",
          "sex":"0",
          "permission":"0",
          "isDelete":"0"
        }
      ]
    }
  },
  {
    "description":"增加用户接口",
    "request":{
      "uri":"/addUser",
      "method":"post",
      "json":{
        "userName":"zhao9",
        "password":"zhaozhao",
        "sex":"0",
        "age":"35",
        "permission":"1",
        "isDelete":"0"
      },
      "cookies":{
        "login":"true"
      }
    },
    "response":{
      "text":"true"
    }
  },
  {
    "description":"增加用户接口",
    "request":{
      "uri":"/updateUserInfo",
      "method":"post",
      "json":{
        "userId":"2",
        "userName":"hahahaha"
      },
      "cookies":{
        "login":"true"
      }
    },
    "response":{
      "text":"true"
    }
  },
  {
    "description":"删除用户接口",
    "request":{
      "uri":"/deleteUser",
      "method":"post",
      "json":{
        "userId":"8"
      },
      "cookies":{
        "login":"true"
      }
    },
    "response":{
      "text":"true"
    }
  }
]

第二步:启动服务

java -jar ./moco-runner-0.11.0-standalone.jar http -p 8888 -c userManager.json

启动服务注意事项

  • 一定的在moco-runner-0.11.0-standalone.jar包下启动,否则找不到包

第三步::使用postman测试mock服务是否可用

第四步:数据的准备 准备用户名等于 abc的数(用于登录结果的验证)

2、已登录成功案例测试为例:

自己在测试中值得的问题

  • java -jar ./moco-runner-0.11.0-standalone.jar http -p 8888 -c userManager.json 启动的端口要和application.properties文件中配置的一样
  • 在getResult()方法中,塞值一定要和mock中请求参数的字段一样
  • 请求的方式要设置好,是已JSON还是key-value的方式
  • 在查询数据库的时候,model定义的字段民要和数据库一致

2.1、直接在用例里面测试验证是否能用

2.2、在xml测试套件是否可用


相关推荐
hai4058726 分钟前
Spring Boot中的响应与分层解耦架构
spring boot·后端·架构
工业甲酰苯胺2 小时前
Spring Boot 整合 MyBatis 的详细步骤(两种方式)
spring boot·后端·mybatis
bjzhang754 小时前
SpringBoot开发——集成Tess4j实现OCR图像文字识别
spring boot·ocr·tess4j
flying jiang4 小时前
Spring Boot 入门面试五道题
spring boot
小菜yh4 小时前
关于Redis
java·数据库·spring boot·redis·spring·缓存
爱上语文5 小时前
Springboot的三层架构
java·开发语言·spring boot·后端·spring
荆州克莱5 小时前
springcloud整合nacos、sentinal、springcloud-gateway,springboot security、oauth2总结
spring boot·spring·spring cloud·css3·技术
serve the people5 小时前
springboot 单独新建一个文件实时写数据,当文件大于100M时按照日期时间做文件名进行归档
java·spring boot·后端
罗政11 小时前
[附源码]超简洁个人博客网站搭建+SpringBoot+Vue前后端分离
vue.js·spring boot·后端
Java小白笔记14 小时前
关于使用Mybatis-Plus 自动填充功能失效问题
spring boot·后端·mybatis