從 0 到 1 搭建 Dubbo 接口自動化測試

實戰 | 從 0 到 1 搭建 Dubbo 接口自動化測試

前言

由於公司 Dubbo 接口數量較多,且核心接口較多,故需要一套 Dubbo 接口自動化框架,來提高測試效率。

1、Dubbo 接口自動化測試框架實現邏輯

實戰 | 從 0 到 1 搭建 Dubbo 接口自動化測試

2、框架具體功能

框架需要
實現功能

功能說明當前版本是否已實現

從 maven 庫自動下載所需 jar 包為了更好的自動化,所有的 provider 的 jar 都從 maven 下載,避免手工導入已實現參數自定義匹配不同的 Dubbo 接口,不同的參數需求已實現斷言功能一個接口是否調用成功,在於斷言是否成功已實現郵件報警功能如果 Dubbo 接口調用 provider 失敗,自動進行郵件報警已實現自動運行利用 jenkins 自動運行已實現

3、關鍵實踐

<code>由於目前階段剛接觸 java 及 Dubbo,本次實現為基本功能實現,數據隔離等沒有做。/<code>

3.1 下載 provider 的 jar 包,並代理聲明 +zookeeper 設置

<code>
<beans>       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:Dubbo="http://code.alibabatech.com/schema/Dubbo"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://code.alibabatech.com/schema/Dubbo
       http://code.alibabatech.com/schema/Dubbo/Dubbo.xsd">

    <application>

    <registry>


    <reference>
/<beans>/<code>

3.2 郵件發送功能

(1)郵件服務器配置在 mailConfig.properties

實戰 | 從 0 到 1 搭建 Dubbo 接口自動化測試

(2)獲取 mailconfig 信息,並封裝成類


<code>public class MailConfig {
    private static final String PROPERTIES_DEFAULT = "mailConfig.properties";
    public static String host;
    public static Integer port;

    public static String userName;
    public static String passWord;
    public static String emailForm;
    public static String timeout;
    public static String personal;
    public static Properties properties;
    static{
        init();
    }

    /**
     * 初始化
     */
    private static void init() {
        properties = new Properties();
        InputStream inputStream = null;
        try{

            inputStream = MailConfig.class.getClassLoader().getResourceAsStream(PROPERTIES_DEFAULT);
            properties.load(inputStream);
            inputStream.close();
            host = properties.getProperty("mailHost");
            port = Integer.parseInt(properties.getProperty("mailPort"));
            userName = properties.getProperty("mailUsername");
            passWord = properties.getProperty("mailPassword");
            emailForm = properties.getProperty("mailFrom");
            timeout = properties.getProperty("mailTimeout");
            personal = " 自動化測試 ";
        } catch(IOException e){
            e.printStackTrace();
        }
    }
}/<code>

(3)封裝發送郵件功能

<code>public class MailUtil {
    private static final String HOST = MailConfig.host;
    private static final Integer PORT = MailConfig.port;
    private static final String USERNAME = MailConfig.userName;
    private static final String PASSWORD = MailConfig.passWord;
    private static final String emailForm = MailConfig.emailForm;
    private static final String timeout = MailConfig.timeout;
    private static final String personal = MailConfig.personal;
    private static JavaMailSenderImpl mailSender = createMailSender();
    /**
     * 郵件發送器
     *

     * @return 配置好的工具
     */
    private static JavaMailSenderImpl createMailSender() {
        JavaMailSenderImpl sender = new JavaMailSenderImpl();
        sender.setHost(HOST);
        sender.setPort(PORT);
        sender.setUsername(USERNAME);
        sender.setPassword(PASSWORD);
        sender.setDefaultEncoding("Utf-8");
        Properties p = new Properties();
        p.setProperty("mail.smtp.timeout", timeout);
        p.setProperty("mail.smtp.auth", "false");
        sender.setJavaMailProperties(p);
        return sender;
    }

    /**
     * 發送郵件
     *
     * @param to 接受人
     * @param subject 主題
     * @param html 發送內容
     * @throws MessagingException 異常
     * @throws UnsupportedEncodingException 異常
     */
    public void sendMail(InternetAddress[] to, String subject, String html) throws MessagingException,UnsupportedEncodingException {
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        // 設置 utf-8 或 GBK 編碼,否則郵件會有亂碼
        MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
        messageHelper.setFrom(emailForm, personal);
        messageHelper.setTo(to);
        messageHelper.setSubject(subject);
        messageHelper.setText(html, false);
        mailSender.send(mimeMessage);
    }
}/<code>

3.3 封裝 Dubbo 接口信息類

把 Dubbo 接口封裝成一個類,方便信息 get 和 set

<code>public class DubboInterfaceInfo {
    private String DubboInterfaceWiki;
    private String DubboInterfacePacketName;
    private String DubboInterfaceClassName;

    private RestRequest request;
    private String responseStatusSuccessful;
    private String responseMessageSuccessful;
    private String DubboInterfaceId;

    public DubboInterfaceInfo() {}

    public String getDubboInterfaceWiki() {
        return this.DubboInterfaceWiki;
    }
    public void setDubboInterfaceWiki(String DubboInterfaceWiki) {
        this.DubboInterfaceWiki = DubboInterfaceWiki;
    }

    public String getDubboInterfacePacketName() {
        return this.DubboInterfacePacketName;
    }
    public void setDubboInterfacePacketName(String DubboInterfacePacketName) {
        this.DubboInterfacePacketName = DubboInterfacePacketName;
    }

    public String getDubboInterfaceClassName() {
        return this.DubboInterfaceClassName;
    }
    public void setDubboInterfaceClassName(String DubboInterfaceClassName) {
        this.DubboInterfaceClassName = DubboInterfaceClassName;
    }

    public RestRequest getRestRequest() {
        return this.request;
    }
    public void setRestRequest(RestRequest request) {
        this.request = request;
    }

    public String getResponseStatusSuccessful() {
        return this.responseStatusSuccessful;
    }
    public void setResponseStatusSuccessful(String responseStatusSuccessful) {
        this.responseStatusSuccessful = responseStatusSuccessful;
    }

    public String getResponseMessageSuccessful() {
        return this.responseMessageSuccessful;
    }
    public void setResponseMessageSuccessful(String responseMessageSuccessful) {
        this.responseMessageSuccessful = responseMessageSuccessful;
    }

    public String getDubboInterfaceId() {

        return this.DubboInterfaceId;
    }
    public void setDubboInterfaceId(String DubboInterfaceId) {
        this.DubboInterfaceId = DubboInterfaceId;
    }
}/<code>

3.4 利用 JMeter 調用 provider 服務,並斷言,郵件報警

利用 Jmeter 調用 provider 服務,並斷言,郵件報警,這些功能封裝成 Dubbo 接口測試類,代碼如下:

<code>public class IPromiseForOrderServiceTest extends AbstractJavaSamplerClient {
    /**
     * CONTEXT
     * 讀取 Dubbo-config.xml 中的內容
     */
    private static final ApplicationContext CONTEXT = new ClassPathXmlApplicationContext("Dubbo-config.xml");
    public DubboInterfaceInfo DubboInterfaceInfo = new DubboInterfaceInfo();
    public String responseSuccess;
    public String responseFail;
    public FreeStockForOrderParam request;
    /**
     * IPromiseForOrderService
     * 此處需要實例化 Dubbo 接口 IPromiseForOrderService,像定義變量一樣實例化
     */
    private static IPromiseForOrderService IPromiseForOrderService;

    /**
     * IPromiseForOrderService
     * 以下方法用於 輸入 Dubbo 接口信息
     */
    public void DubboInterfaceInfoInitialization () {
        DubboInterfaceInfo.setDubboInterfaceWiki("......");
        DubboInterfaceInfo.setDubboInterfacePacketName("......");
        DubboInterfaceInfo.setDubboInterfaceClassName("......");
        DubboInterfaceInfo.setDubboInterfaceId("......");
        DubboInterfaceInfo.setResponseStatusSuccessful("0");
        DubboInterfaceInfo.setResponseMessageSuccessful("success");
        String orderNo = "orderNo";
        String operater="";
        String channel="";
        String operateId="operateId";

        String version= PromiseVersion.V_1_0_0.getVersion();
        request = new FreeStockForOrderParam();
        if (orderNo != null || orderNo.length() > 0) {
            request.setOrderNo(orderNo);
        }
        if (operater != null || operater.length() > 0) {
            request.setOperater(operater);
        }
        if (channel != null || channel.length() > 0) {
            request.setChannel(channel);
        }
        if (operateId != null || operateId.length() > 0) {
            request.setOperateId(operateId);
        }
        if (version != null || version.length() > 0) {
            request.setVersion(version);
        }
        RestRequest<freestockfororderparam> req = new RestRequest<freestockfororderparam>();
        req.setRequest(request);
        DubboInterfaceInfo.setRestRequest(req);
    }


    @Override
    public void setupTest(JavaSamplerContext arg0){
        IPromiseForOrderService=(IPromiseForOrderService)CONTEXT.getBean("......");
    }

    @Override
    public SampleResult runTest(JavaSamplerContext javaSamplerContext) {
        SampleResult sr = new SampleResult();

        try {
            sr.sampleStart();
            RestResponse responseData = IPromiseForOrderService.freeSaleStock(DubboInterfaceInfo.getRestRequest());
// 自定義 Dubbo 調用成功和失敗的郵件正文內容
            responseSuccess =
                             "Dubbo 接口: "
                                     + DubboInterfaceInfo.getDubboInterfaceId() + " 請求成功\\r\\n"
                                     + "WIKI 地址: " + DubboInterfaceInfo.getDubboInterfaceWiki() + "\\r\\n"
                                     + "PacketName: " + DubboInterfaceInfo.getDubboInterfacePacketName() + "\\r\\n"
                                     + "ClassName: " + DubboInterfaceInfo.getDubboInterfaceClassName() + "\\r\\n"
                                    ;
            responseFail =
                    "Dubbo 接口: " + DubboInterfaceInfo.getDubboInterfaceId() + " 請求失敗\\r\\n"
                            + "WIKI 地址: " + DubboInterfaceInfo.getDubboInterfaceWiki() + "\\r\\n"
                            + "PacketName: " + DubboInterfaceInfo.getDubboInterfacePacketName() + "\\r\\n"

                            + "ClassName" + DubboInterfaceInfo.getDubboInterfaceClassName() + "\\r\\n"
                            + " 請求參數為:Channel: " + request.getChannel() +
                                            " / operater: " + request.getOperater() +
                                            " / OperateId: " + request.getOperateId() +
                                            " / OrderNo: " + request.getOrderNo() +
                                            " / Version: " + request.getVersion()
                            + "\\r\\n"
                            + " 返回結果為:"
                            + "ResponseStatus: " + responseData.getStatus()
                            + " / ResponseMessage: " + responseData.getMessage()
                            + " / ResponseResult: " + responseData.getResult();


            /**
             * 郵件定義及發送
             */
            InternetAddress[] address = new InternetAddress[2];
            try {
                address[0] = new InternetAddress("[email protected]");
                address[1] = new InternetAddress("[email protected]");
            } catch (AddressException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            MailUtil mailUtil = new MailUtil();

            if ((DubboInterfaceInfo.getResponseStatusSuccessful().equals(responseData.getStatus())) && (DubboInterfaceInfo.getResponseMessageSuccessful().equals(responseData.getMessage()))) {
                sr.setSuccessful(true);
                sr.setResponseData("responseData: " + responseData, "utf-8");
                System.out.println(responseSuccess);
                mailUtil.sendMail(address,"Dubbo 接口:" + DubboInterfaceInfo.getDubboInterfaceId() + " 請求成功 ",responseSuccess.toString());

            } else {
                sr.setSuccessful(false);
                System.out.println(responseFail);
                mailUtil.sendMail(address,"Dubbo 接口:" + DubboInterfaceInfo.getDubboInterfaceId() + " 請求失敗 ",responseFail.toString());
            }

            sr.sampleEnd();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return sr;
    }


}/<freestockfororderparam>/<freestockfororderparam>/<code>

3.5 利用 Testng 註釋,調用 Dubbo 接口類,進行測試

<code>public class TestngTest {
    @Test()
    public void testDubboInterface() {
        JavaSamplerContext arg0 = new JavaSamplerContext(new Arguments());

        Dubbo 接口測試類 TestForIPromiseForOrderService = new Dubbo 接口測試類 ();
        TestForIPromiseForOrderService.DubboInterfaceInfoInitialization();
        TestForIPromiseForOrderService.setupTest(arg0);
        SampleResult sr = TestForIPromiseForOrderService.runTest(arg0);
    }
}/<code>

4、利用 Jenkins 自動化運行 Dubbo 測試項目

實戰 | 從 0 到 1 搭建 Dubbo 接口自動化測試

至此,大功告成,你可以完成 Dubbo 接口自動化測試了。另,接下來可以加入關聯、測試數據分離等功能,讓框架變得更加易用。



分享到:


相關文章: