我們在做性能測試時,有時需要自己編寫測試腳本,很多測試工具都支持自定義編寫測試腳本,比如LoadRunner就有很多自定義腳本的協(xié)議,比如"C?Vuser","Java?Vuser"等協(xié)議.同樣,Jmeter也支持自定義編寫的測試代碼,不過與LoadRunner不同的是,Jmeter沒有自帶編譯器,需要借助第三方編譯器才能實現(xiàn).下面舉一個簡單的Java自定義測試代碼例子,使用Java編譯器編寫測試代碼(Java編譯器可以用Eclipse,JBulider等),實現(xiàn)功能為:在測試前輸入任意一個字符串,然后判斷該字符串的長度是否大于5,如果大于則測試結(jié)果成功,否則測試結(jié)果位失敗,然后在放到Jmeter中模擬10個用戶測試,同時運行這段代碼,具體實現(xiàn)如下:
創(chuàng)新互聯(lián)建站主要從事網(wǎng)站制作、成都網(wǎng)站設(shè)計、網(wǎng)頁設(shè)計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)龍川,十多年網(wǎng)站建設(shè)經(jīng)驗,價格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):028-86922220
1.打開Java編譯器,新建一個項目"TestLength",然后新建一個包"app".
2.從Jmeter的安裝目錄lib/ext中拷貝兩個文件"ApacheJMeter_core.jar"和"ApacheJMeter_java.jar"到"Tester"的項目中,然后引入這兩個JAR文件.(具體的引入方法參考各個Java編譯器的使用方法)
3.在"app"包中新建一個類,名字叫"TestLength",不過這個類要繼承"AbstractJavaSamplerClient"類,如果項目引入步驟二中的兩個文件,就可以找到"AbstractJavaSamplerClient"類了.
4."TestLength"類在繼承"AbstractJavaSamplerClient"類的同時也會繼承四個方法,分別是"getDefaultParameters","setupTest","runTest"和"teardownTest"方法."getDefaultParameters"方法主要用于設(shè)置傳入的參數(shù);"setupTest"方法為初始化方法,用于初始化性能測試時的每個線程."runTest"方法為性能測試時的線程運行體;"teardownTest"方法為測試結(jié)束方法,用于結(jié)束性能測試中的每個線程.
5.具體實現(xiàn)代碼如下:
package?app;
import?org.apache.jmeter.config.Arguments;
import?org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import?org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import?org.apache.jmeter.samplers.SampleResult;
import?com.passpod.core.t8.*;
/**
*?@author樂以忘憂
*
*?TODO?To?change?the?template?for?this?generated?type?comment?go?to
*?Window?-?Preferences?-?Java?-?Code?Style?-?Code?Templates
*/
public?class?TestLength?extends?AbstractJavaSamplerClient{
private?SampleResult?results;
private?String?testStr;
//初始化方法,實際運行時每個線程僅執(zhí)行一次,在測試方法運行前執(zhí)行,類似于LoadRunner中的init方法
public?void?setupTest(JavaSamplerContext?arg0)?{
results?=?new?SampleResult();
testStr?=?arg0.getParameter("testString",?"");
if?(testStr?!=?null??testStr.length()??0)?{
results.setSamplerData(testStr);
}
}
//設(shè)置傳入的參數(shù),可以設(shè)置多個,已設(shè)置的參數(shù)會顯示到Jmeter的參數(shù)列表中
public?Arguments?getDefaultParameters()?{
Arguments?params?=?new?Arguments();
params.addArgument("testStr",?"");???//定義一個參數(shù),顯示到Jmeter的參數(shù)列表中,第一個參數(shù)為參數(shù)默認(rèn)的顯示名稱,第二個參數(shù)為默認(rèn)值
return?params;
}
//測試執(zhí)行的循環(huán)體,根據(jù)線程數(shù)和循環(huán)次數(shù)的不同可執(zhí)行多次,類似于LoadRunner中的Action方法
public?SampleResult?runTest(JavaSamplerContext?arg0)?{
int?len?=?0;
results.sampleStart();?????//定義一個事務(wù),表示這是事務(wù)的起始點,類似于LoadRunner的lr.start_transaction
len?=?testStr.length();
results.sampleEnd();?????//定義一個事務(wù),表示這是事務(wù)的結(jié)束點,類似于LoadRunner的lr.end_transaction
if(len??5){
System.out.println(testStr);
results.setSuccessful(false);???//用于設(shè)置運行結(jié)果的成功或失敗,如果是"false"則表示結(jié)果失敗,否則則表示成功
}else???
results.setSuccessful(true);
return?results;
}
//結(jié)束方法,實際運行時每個線程僅執(zhí)行一次,在測試方法運行結(jié)束后執(zhí)行,類似于LoadRunner中的end方法
public?void?teardownTest(JavaSamplerContext?arg0)?{
}
}
6.把上面的例子打包,然后把生成的"TestLength.jar"文件拷貝到Jmeter的安裝目錄lib/ext下.
7.運行Jmeter,添加一個線程組,然后在該線程組下面添加一個Java請求(在Sampler中),在Java請求的類名稱中選擇咱們剛創(chuàng)建的類"app.TestLength",在下面參數(shù)列表的"testStr"后面輸入要測試的字符串,然后添加一個監(jiān)聽器(聚合報告),設(shè)置一下模擬的用戶數(shù)就可以測試了.如果測試不成功,Jmeter會在它自己個輸出框中拋出這個字符串.
通過上面的例子我們可以發(fā)現(xiàn),使用Jmeter自定義Java測試代碼,配合Jmeter自帶的函數(shù),就可以實現(xiàn)出LoadRunner中"Java?Vuser"協(xié)議的絕大多數(shù)功能,而且是沒有用戶數(shù)限制和完全免費的(嘿嘿).上面的例子非常簡單,而且沒有任何實際意義,只是一個簡單的Jmeter測試代碼示例,用于拋磚引玉,希望大家一起交流,共同?進步.
--------------------------DateUtil類
/**
* @author 王炳焱
* 創(chuàng)建日期:2007-5-21
* 項目名稱:te
* 文件名稱:DateUtil
*/
package test0521;
/**
* @author Administrator
*
*/
public class DateUtil {
public int year;// 用于表示年份
public int month;// 用于表示月份
public int day;// 用于表示天數(shù)
private boolean isLeapYear = false;// 用于表示是否為閏年.初始值為false
DateUtil() {
}
DateUtil(int year, int month) {// 用于初始化year變量和month變量
this.year = year;
this.month = month;
}
public boolean isLeapYear() {// 用于判斷年份是否為閏年
this.isLeapYear = (this.year % 4 == 0 this.year % 100 != 0)
|| (this.year % 400 == 0);//閏年條件
return this.isLeapYear;
}
public int getMonthDays() {// 用于計算并取得該月的天數(shù)
int[] bigMonth = { 1, 3, 5, 7, 8, 10, 12 };//31天的月份
for (int i = 0; i bigMonth.length; i++) {
if (this.month == bigMonth[i]) {
this.day = 31;
return this.day;
}
}
if (this.month == 2 this.isLeapYear()) {//閏年2月
this.day = 29;
return this.day;
}
if (this.month == 2) {//平年2月
this.day = 28;
return this.day;
}
this.day = 30;//除去31天的月份和2月,其他月份都為30天
return this.day;
}
}
---------------Test類
/**
* @author 王炳焱
* 創(chuàng)建日期:2007-5-21
* 項目名稱:te
* 文件名稱:Test
*/
package test0521;
/**
* @author Administrator
*
*/
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO 自動生成方法存根
DateUtil dateUtil = new DateUtil(2008, 1);//輸入年份與月份
String str = "平年";
if (dateUtil.isLeapYear()) {//根據(jù)判斷閏年返回布爾值生成對應(yīng)字符串
str = "閏年";
}
System.out.println(dateUtil.year + "年為"+str);
System.out.println(dateUtil.month + "月有" + dateUtil.getMonthDays()+ "天");
}
}
control-1.0.1-dist.zip。 解壓。
2. 用命令行來到解壓的文件夾下: \selenium-remote-control-0.9.2\selenium-server-0.9.2
3. 運行: java -jar selenium-server.jar 啟動selenium server (務(wù)必啟動!!)
4. 在Eclipse創(chuàng)建一個項目,在項目的build path里面加上junit.jar和selenium-java-client-driver.jar(這個在剛解壓的包里面)
5. 先利用firefox selenium IDE來錄制檢測頁面檢測功能用的junit代碼。
6. 在項目里面新建一個class(junit用例):將上面的junit代碼帖于此。
7. 根據(jù)eclipse的錯誤提示來增加相應(yīng)要import的類
8. 在進行測試前,最好將對應(yīng)瀏覽器關(guān)閉,否則容易出錯。
9. 然后在Eclipse里運行 “Run As - unit Test”即可看到自動化的范例.
10.運行期間,會彈出ie窗口,自動進 行操作測試。檢測完后,若junit顯示為“綠色”則表示成功。
下面粘貼一下那個測試小程序
import com.thoughtworks.selenium.SeleneseTestCase;public class Untitled extends SeleneseTestCase {
public void setUp() throws Exception {
//由于selenium 對*firefox不支持3.6版本的.只能支持3.0版本.所以,最好將selenium IDE錄制的代碼中的firefox改為ie進行測試。
//setUp("", "*firefox");
setUp("", "*iexplore");
}
public void testUntitled() throws Exception {
selenium.open("/");
selenium.type("q", "baidu");
selenium.click("btnG");
selenium.waitForPageToLoad("30000");
selenium.click("link= 百度一下,你就知道");
//添加斷言進行測試:
// assertTrue(selenium.isTextPresent("OpenQA: Selenium")); //測試出錯,程序退出
assertTrue(selenium.isTextPresent("百度一 下,你就知道")); //測試成功,程序繼續(xù)
}
//用于讓測試的頁面關(guān)閉.若不寫,則頁面不會關(guān)閉
public void tearDown() throws Exception {
selenium.stop();
}
}
(7)
7.1
selenium 常用操作有:open,type,click,select,selectFrame:
1. open("/")打開的是當(dāng)前的網(wǎng)址;selenium.open("/dmmc/"):在當(dāng)前的網(wǎng)址后面追回/dmmc/;
2. type,click,select,selectFrame各方法使用時,對元素的定位都可采用元素ID 或 xpath方式;
3. type,click,select,selectFrame去選擇元素時,可以直接用元素的ID作為標(biāo) 記.
4. 如:selenium.type("loginName", "coship");;采用xpath方式時,則格式如://元素名1[元素屬性名1='元素屬性值1']/元素名2[元素屬性名2='元素 屬 性值2']/....
如:selenium.type("http://input[@name='admin.password']", "coship")7.2
常用命令用法:
1)
type的兩種不同定位方式:
selenium.type("loginName", "coship");
//以下語句的"xpath="可以省略
selenium.type("xpath=//input[@name='admin.password']", "coship");
2)
click的兩種不同定位方式:
selenium.click("imageField"); 即是通過ID定位:input type="submit" value=" " id="imageField"
selenium.click("http://input[@type='submit']"); (通過屬性input-type)
selenium.click("http://input[@value='確定']"); (通過屬性input-value)
selenium.click("http://input[@name='devTypeIds' and @value='000002']") (還可通過屬性@id)
3)
點擊鏈接方式:
對于動態(tài)內(nèi)容的獲取,盡量避 免采用第一種方式(若內(nèi)容變了,則出錯),而采用第二種方式.
實現(xiàn)方式一:
點擊鏈接:a href=..801830456628/a
selenium.click("link=801830456628");
實現(xiàn)方式二:
獲取id=adminList的table中的tbody下的第三行,第二列中的a href元素。
selenium.click("http://table[@id='adminsList']/tbody/tr[3]/td[2]/a");
4)
選 擇下拉框:
實現(xiàn)方式一:
selenium.select("status", "label=啟用");
即 是:select id="status"option value="1"啟用/option/select
實現(xiàn)方式二:
selenium.select("xpath=//SELECT[@id='status']", "index=1");
具體應(yīng)用,請見以下實例。7.3
實例:
用于檢測abmc系統(tǒng)各模塊功能是否正常。
方式:
用selenium IDE錄制abmc系統(tǒng)各模塊功能操作.(前提是:這些操作,這些功能都是正確成功),以后當(dāng)abmc系統(tǒng)升級,更改后,即可運行此腳本,來檢查升級是否 影響系統(tǒng)功能實現(xiàn)。若系統(tǒng)更改有錯,則selenium中運行中某一步驟時,會出錯退出。
如:
系統(tǒng)更改后導(dǎo)致某一頁面打不開,這時 selenium運行到此頁面時,就不能繼續(xù)往下操作,就會出錯而退出。注意:
1.同時,也可在測試代碼中添加一些斷言判斷來判斷成功,失敗。
2.
對于firefox selenium IDE錄制的腳本要進行適當(dāng)?shù)男薷?盡量讓selenium用元素ID來定位操作元素,而不通過元素名(元素名易變化)。
3.
若selenium RC檢測代碼出錯,也不一定是系統(tǒng)升級有問題,可能是系統(tǒng)升級后,有些數(shù)據(jù)刪除,修改了,selenium RC在回放操作時,找到原來錄制時對應(yīng)的數(shù)據(jù)而出錯。具體代碼如下:
//對于click,select,selectFrame去選擇元素時,可以直接用元素的ID作為標(biāo)記.// 如:selenium.click("元素ID");public class AbmcSeleniumTest extends SeleneseTestCase {
public void setUp() throws Exception {
setUp("", "*iexplore");
}
public void testUntitled() throws Exception {
selenium.open("/abmc/");
//type的兩種不同定位方式
selenium.type("loginName", "coship");
//以下語句 的"xpath="可以省略
selenium.type("xpath=//input[@name='admin.password']", "coship");
// selenium.click("imageField"); 即是通過ID 定位:input type="submit" value=" " id="imageField"
selenium.click("http://input[@type='submit']");
//等待一個新的頁面加載。 以毫秒為單位,超過后該命令將返回錯誤。
selenium.waitForPageToLoad("30000");
//即選擇frame src="device/index.jsp" id="mainFrame"
selenium.selectFrame("mainFrame");
//對于動態(tài)內(nèi)容的獲取,盡量避免采用第一種方式 (若內(nèi)容變了,則出錯),而采用第二種方式
//點擊鏈接:a href=..801830456628/a
// selenium.click("link=801830456628");
//實現(xiàn)方式二:獲取id=adminList的table中的tbody下的第三行,第二列中的a href元素。
selenium.click("http://table[@id='adminsList']/tbody/tr[3]/td[2]/a");
selenium.waitForPageToLoad("30000");
selenium.click("http://input[@value=' 返回']");
selenium.waitForPageToLoad("30000");
//因為有多個“查看應(yīng)用列表”,若不指定,默認(rèn)獲取第一個
selenium.click("link=查看應(yīng)用列表");
selenium.click("btn_dsure");
// 方式一:
//selenium.click(" //a[@onclick=\"showPage('應(yīng)用列表','deviceAppList.action?device.swType=2device.deviceId=0000257device.deviceName=801830456628device.specName=DevTyp',750,400)\"]");
//方式二:
selenium.click("http://table[@id='adminsList']/tbody/tr[3]/td[5]/span[1]/a");
selenium.click("btn_dsure");
selenium.selectFrame("relative=up");
selenium.selectFrame("leftFrame");
selenium.click("link=應(yīng)用文件管理");
selenium.click("link=應(yīng)用文件信息");
selenium.selectFrame("relative=up");
selenium.selectFrame("mainFrame");
selenium.click("http://a[@onclick=\"showPage('匹配終端類型','appTypeList.action?application.appId=01application.appName=maliao',750,400)\"]");
selenium.click("btn_dsure");
selenium.click("http://table[@id='adminsList']/tbody/tr[7]/td[8]/span[2]/a");
selenium.waitForPageToLoad("30000");
selenium.click("http://input[@name='devTypeIds' and @value='000002']");
selenium.click("http://input[@value='確定']");
selenium.waitForPageToLoad("30000");
selenium.click("http://a[@onclick=\"showPage('匹配終端類型','appTypeList.action?application.appId=01application.appName=maliao',750,400)\"]");
selenium.click("btn_dsure");
selenium.selectFrame("relative=up");
selenium.selectFrame("leftFrame");
selenium.click("link=終端應(yīng)用管理");
selenium.click("link=終端應(yīng)用許可");
selenium.selectFrame("relative=up");
selenium.selectFrame("mainFrame");
// selenium.select("status", "label=啟用"); 即是:select id="status"option value="1"啟 用/option/select
selenium.select("xpath=//SELECT[@id='status']", "index=1");
selenium.click("http://input[@type='image']");
selenium.waitForPageToLoad("30000");
selenium.click("http://input[@type='image']");
selenium.waitForPageToLoad("30000");
selenium.selectFrame("relative=up");
//即 選擇frame src="device/index.jsp" id="mainFrame"
selenium.selectFrame("topFrame");
selenium.click("link=注銷");
//若要測試其 它的網(wǎng)頁,可以繼續(xù)selenium.open(..)
}
}
#web測試技術(shù)
可以用main函數(shù)和JUnit來寫測試代碼。main是最早使用的,但是現(xiàn)在更流行的測試工具是JUnit。
JUnit是一個Java語言的單元測試框架。它由Kent Beck和Erich Gamma建立,逐漸成為源于Kent Beck的sUnit的xUnit家族中最為成功的一個。 JUnit有它自己的JUnit擴展生態(tài)圈。多數(shù)Java的開發(fā)環(huán)境都已經(jīng)集成了JUnit作為單元測試的工具。
下面是一些具體的編寫測試代碼的技巧或較好的實踐方法:
1. 不要用TestCase的構(gòu)造函數(shù)初始化Fixture,而要用setUp()和tearDown()方法。
2. 不要依賴或假定測試運行的順序,因為JUnit利用Vector保存測試方法。所以不同的平臺會按不同的順序從Vector中取出測試方法。
3. 避免編寫有副作用的TestCase。例如:如果隨后的測試依賴于某些特定的交易數(shù)據(jù),就不要提交交易數(shù)據(jù)。簡單的回滾就可以了。
4. 當(dāng)繼承一個測試類時,記得調(diào)用父類的setUp()和tearDown()方法。
5. 將測試代碼和工作代碼放在一起,一邊同步編譯和更新。(使用Ant中有支持junit的task.)
6. 測試類和測試方法應(yīng)該有一致的命名方案。如在工作類名前加上test從而形成測試類名。
7. 確保測試與時間無關(guān),不要依賴使用過期的數(shù)據(jù)進行測試。導(dǎo)致在隨后的維護過程中很難重現(xiàn)測試。
8. 如果你編寫的軟件面向國際市場,編寫測試時要考慮國際化的因素。不要僅用母語的Locale進行測試。
9. 盡可能地利用JUnit提供地assert/fail方法以及異常處理的方法,可以使代碼更為簡潔。
10.測試要盡可能地小,執(zhí)行速度快。
11.不要硬性規(guī)定數(shù)據(jù)文件的路徑。
12.利用Junit 的自動異常處理書寫簡潔的測試代碼
事實上在Junit 中使用try-catch 來捕獲異常是沒有必要的,Junit 會自動捕獲異常。那些沒有被捕獲的異常就被當(dāng)成錯誤處理。
13. 充分利用Junit 的assert/fail 方法
assertSame()用來測試兩個引用是否指向同一個對象
assertEquals()用來測試兩個對象是否相等
14. 確保測試代碼與時間無關(guān)
15. 使用文檔生成器做測試文檔。