前言
由於公司 Dubbo 接口數量較多,且核心接口較多,故需要一套 Dubbo 接口自動化框架,來提高測試效率。
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
(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 測試項目
至此,大功告成,你可以完成 Dubbo 接口自動化測試了。另,接下來可以加入關聯、測試數據分離等功能,讓框架變得更加易用。
閱讀更多 霍格沃茲軟件測試學院 的文章