[oracle@OracleTest oracle]$ sqlplus log
SQL> connect / as sysdba
SQL> shutdown [immediate]
SQL> exit
2.停止Listener
[oracle@OracleTest oracle]$ lsnrctl stop
3.停止HTTP服務
[root@OracleTest /root]# service httpd stop
4.用su或者重新登錄到root(如想重新安裝可以保留oracle用戶,省得輸入環境變量了) 5.將安裝目錄刪除
[root@OracleTest /root]# rm -rf /u01/oracle/
[root@OracleTest /root]# rm -rf /u01/oraInventory/
6.將/usr/bin下的文件刪除
[root@OracleTest /root]# rm /usr/local/bin/dbhome
[root@OracleTest /root]# rm /usr/local/bin/oraenv
[root@OracleTest /root]# rm /usr/local/bin/coraenv
7.將/etc/oratab刪除
[root@OracleTest /root]# rm /etc/oratab
8.將/etc/oraInst.loc刪除
[root@OracleTest /root]# rm /etc/oraInst.loc
9.將oracle用戶刪除(若要重新安裝,可以不刪除)
[root@OracleTest /root]# userdel –r oracle
10.將用戶組刪除(若要重新安裝,可以不刪除)
[root@OracleTest /root]# groupdel oinstall
[root@OracleTest /root]# groupdel dba
11.將啟動服務刪除
[root@OracleTest /root]# chkconfig --del dbora
到此為止重啟后,你的
Linux系統下的Oracle數據庫已完全刪除了?。?!
以上是CentOS5.4+Oracle 11g的環境。
包括用戶的登錄腳本,數據庫自動啟動關閉的腳本,和Listener自動啟動的腳本。
要是有可能連創建數據庫的腳本也保存下來。
1.停止oepnfire服務
[root@openfire.clvn.com.cn ~]# su - openfire
-bash-4.1$ cd /usr/local/openfire/bin
-bash-4.1$ ./openfire stop
2.找到openfire配置文件
[root@openfire.clvn.com.cn ~]# cd /usr/local/openfire/conf/
[root@openfire.clvn.com.cn conf]# ls
available-plugins.xml crowd.properties openfire.xml security.xml server-update.xml
[root@openfire.clvn.com.cn conf]# vim openfire.xml
找到
<setup>true</setup>
將其刪除
3.重新啟動openfire
[root@openfire.clvn.com.cn ~]# su - openfire
-bash-4.1$ cd /usr/local/openfire/bin
-bash-4.1$ ./openfire start
Starting openfire
今天寫個自動刷新頁面的腳本,發現在啟動firefox的時候,出現一個類似如下的錯誤:
請在文本框輸入文字15:22:12.031 WARN - GET /selenium-server/driver/?cmd=getNewBrowserSession&1=*fir efox&2=http://www.google.com HTTP/1.1 java.lang.RuntimeException: Firefox refused shutdown while preparing a profile at org.openqa.selenium.server.browserlaunchers.FirefoxCustomProfileLaunc her.waitForFullProfileToBeCreated(FirefoxCustomProfileLauncher.java:277) |
后來查了google發現問題是selenium不支持高版本firefox, 解決方案如下:
1、用winrar打開selenium-server.jar;
2、查找兩個目錄:customProfileDirCUSTFFCHROME和customProfileDirCUSTFF;
3、搜索每個目錄,對每個文件install.rdf,編輯如下行:
修改
<!-- Firefox --> <em:targetApplication> <Description> <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <em:minVersion>1.4.1</em:minVersion> <em:maxVersion>3.5.*</em:maxVersion> </Description> </em:targetApplication> 為 <!-- Firefox --> <em:targetApplication> <Description> <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <em:minVersion>1.4.1</em:minVersion> <em:maxVersion>3.6.*</em:maxVersion> </Description> </em:targetApplication> |
還可以改得更加大,那么就可以支持4.0 的firefox了
另外,在參數化時,對于一次壓力
測試中均只能用一次的資源應該怎么參數化呢?就是說這些資源用了一次就不能在用了的。
?。瓍祷瘯r,在select next row選擇unique,update value on選擇 each occurence,
1. 迭代跟虛擬用戶數沒什么必然聯系
迭代是這樣的:
迭代1次 迭代2次 迭代3次
用戶1 X1 X2 X3
用戶2 Y1 X2 Y3
其中的X1-3 Y1-3是參數,參數規則就是二樓說的
這么兩個用戶是根據你的rump up 上來的,比如5秒上兩個用戶,那么用戶1和2就在5秒之內加載進來的,不知道說清楚了沒。
第二個問題就簡單了,只能用一次的參數,首先確保你的參數足夠,另外規則選擇的時候,注意選擇唯一
迭代次數只是對你設置了迭代次數的action進行迭代,而用戶數可以理解為對整個錄制過程的迭代(只是各個用戶不同) 而且增加并發量可以通過增加用戶來達到 還可以設置集合點來增加某個操作的并發量
假如一個腳本,設置最大并發量為10,每5秒中增加2個并發用戶,而Action設置的迭代為10次:
當開始至2秒時,加載了2個用戶,這2個用戶分別開始運行,并都運行10次,不管這個2個用戶運行10次是否結束,當下一個2兩秒到來時,即開始至第4秒時又加載了2個用戶,這2個又運行10次;就這樣一直加載到10個并發用戶,然后當每個用戶都運行完10次時就結束。
這樣中間最大并發是10個,但不一定能達到10個,因為在加載最后幾個時,前面的有可能已經運行結束,所以如果要真正達到最大并發10就必須設置集合點來完成
不過也不一定非要設置集合點才能實現同時處在running的狀態有10個用戶。
設置duration也是可以的。不過那就不只每個用戶運行10次了。
如果想實現用戶迭代10次,并且想同時running為10個用戶,就應該設置集合點。
迭代(Iterate)設計,或者我們稱之為增量(Incremental)設計的思想和XP提倡的Evolutionary Design有異曲同工之妙。
注意:1、 參數類型:在創建參數的時候,我選擇了參數類型為File。參數類型共有9 種,現在來簡單介紹一下所有的參數類型以及意義。
1.1、 DateTime:在需要輸入日期/時間的地方,可以用 DateTime 類型來替代。其屬性設置也很簡單,選擇一種格式即可。當然也可以定制格式。
1.2、 Group Name:很少用到。在實際運行中,LoadRunner 使用該虛擬用戶所在的Vuser Group 來代替。但是在 VuGen 中運行時,Group Name將會是None。
1.3、 Load Generator Name :在實際運行中, LoadRunner 使用該虛擬用戶所 在LoadGenerator 的機器名來代替。
1.4、 Iteration Number :在實際運行中,LoadRunner 使用該測試腳本當前循環的次數來代替。
1.5、 Random Number:隨機數。很簡單。在屬性設置中可以設置產生隨機數的范圍。
1.6、 Unique Number:唯一的數。在屬性設置中可以設置第一個數以及遞增的數的大小。
注意:使用該參數類型必須注意可以接受的最大數。例如:某個文本框能接受的最大數為99。當使用該參數類型時,設置第一個數為 1,遞增的數為1,但100個虛擬用戶同時運行時,第100 個虛擬用戶輸入的將是 100,這樣腳本運行將會出錯。這里說的遞增意思是各個用戶取第一個值的遞增數,每個用戶相鄰的兩次循環之間的差值為 1。舉例說明:假如起始數為 1,遞增為 5,那么第一個用戶第一次循環取值 1,第二次循環取值 2;第二個用戶第一次循環取值為 6,第二次為 7;依次類推。
1.7、 Vuser ID:設置比較簡單。在實際運行中,LoadRunner 使用該虛擬用戶的 ID 來代替,該 ID 是由 Controller 來控制的。但是在 VuGen 中運行時,Vuser ID 將會是 –1。
1.8、 File:需要在屬性設置中編輯文件,添加內容,也可以從現成的數據庫中取數據
1.9、 User Defined Function:從用戶開發的 dll 文件提取數據。
用HTTP協議錄制了一個包含登錄、瀏覽、退出過程的腳本,錄制時都放到Action部分,這時腳本設置了迭代后可以多次重復運行,但是出于處理邏輯,一旦將登錄腳本放到Init部分后,就無法正常進行迭代運行了。今天專門找個時間做了嘗試,發現可能出現這兩種錯誤。
1、這是我犯的一個低級錯誤。在我將登錄腳本移到Init部分時,將登錄腳本之后的瀏覽操作前面的web_reg_find腳本也一起移了過去,結果運行完Init部分腳本就出錯了。錯誤提示:
Error -27259: Pending web_reg_save_param/reg_find/create_html_param[_ex] request(s) detected and reset at the end of the Init section
這種錯誤的現象是沒有進行迭代已經出錯了,錯誤提示也很明確。這時只要把web_reg_find放回Action部分的正確的位置即可。
2、單次運行正確,但是多次迭代運行時出錯,錯誤提示:
Error -27985: There is no context for HTML-based functions. A previous function may not have used "Mode=HTML" or downloaded only non-HTML page(s), or the context has been reset (e.g., due to a GUI-based function)
這種錯誤可能比較常見,原因是在Runtime Settings的Browse Emulation中設置了Simulate a new user on each iteration引起的。由于這個設置導致每次迭代時都會模擬一個新的用戶,此時這個新的用戶并沒有執行init操作而失敗了,也即是錯誤提示中的There is no context。
這里涉及到一個知識點就是在Rumtime Settings的迭代設置中,迭代運行次數只對Action部分有效,而Init部分和End部分還是只運行一次的。這時如果設置了“Simulate a new user on each iteration”,將出現上面的第2種錯誤。
一、概述
目前,持續集成已成為當前許多
軟件開發團隊在整個軟件開發生命周期內側重于保證代碼質量的常見做法。隨著
測試的自動化率逐步提高,每天要需要自動執行的
測試用例也就越來越多了,當我們發現,跑一次完整的測試需要幾個小時,測試的速度已遠遠跟不上編譯的速度的時候,我們自然要考慮如何加快測試的速度了——分布式執行測試用例,顯然是一個不錯的辦法,本文正是講述如何利用Hudson來實現
自動化測試的分布式執行。
二、基本概念
1.什么是持續集成
簡而言之,持續集成(Continuous Integration)是一種軟件開發實踐,即團隊開發成員經常集成它們的
工作,通常每個成員每天至少集成一次,也就意味著每天可能會發生多次集成。每次集成都通過自動化的構建(包括編譯,發布,自動化測試)來驗證,從而盡快地發現集成錯誤。
持續集成可以幫助我們做到:
1. 軟件構建自動化
2. 持續自動的構建檢查
3. 持續自動的構建測試
4. 構件生成后續過程的自動化
關于持續集成的更多概念和知識,本文不做深入闡述,有興趣的讀者可以參考以下鏈接:
2.關于Hudson
沒錯,Hudson正是一個能幫助我們實現持續集成的平臺。確切來說,Hudson是一個可擴展的持續集成引擎。 主要用于:
1. 持續、自動地構建/測試軟件項目
2. 監控一些定時執行的任務
更多關于Hudson的介紹和說明,請參考以下鏈接:
持續集成工具Hudson
三、分布式測試
1.串行執行測試
一般,我們會在Hudson上配置三個任務,分別是編譯任務、快速測試任務、慢速(完整)測試任務。這三個任務一般是順序串行執行的,上一個任務執行完畢了之后,下一個任務才能開始執行。
2.化整為零
串行執行測試,當需要運行的自動化測試用例較多時,任務執行的速度顯然不會讓我們滿意,尤其是完整測試任務。如何加快執行速度呢 我們首先會想到的是,可以化整為零,把slowtest任務(完整測試任務)分成多個小任務,這樣,就可以在多臺機器上同時執行,從而加快執行速度了。
然而,這樣的做法,缺點也很明顯——測試結果也被拆分,而且維護成本較高:
①slowtest的測試結果被拆分到各個小任務里,測試結果不方便統一顯示和分析。
②為達到最大速度,需要我們人工來把slowtest任務拆分成跟已有測試機器數量相等的測試任務,如果測試機器的數量新增或減少了,就需要我們再次人工調整任務。
③需要我們人工來指定不同的測試用例,平均分給各個測試任務,如果測試用例數量發生變化,也需要我們再次調整設置。 3.分布式執行!
一般的任務,是不能并發調度執行的,有多個構建請求時,即使有多個測試機器是空閑的,也必須按時間順序,一個接一個運行,典型的情況如下圖所示。
因此,上述化整為零的做法把slowtest任務拆分為多個子任務,從而達到多個任務同時可以同時執行的效果。
實際上,要加快自動化測試的速度,不一定需要多個任務同時執行——我們只需要多個構建同時執行。Hudson任務設置里有一個選項
可以設置任務是否可以多個構建同時執行。我們把這個選項勾選上后,當同時有多個構建請求時,只要有N個測試機器是空閑的,那就可以有N個構建同時執行!
4.遠程控制
Hudson可以設置一個任務構建完成后自動觸發另外的任務構建。這樣,編譯任務、快速測試任務、完整測試任務可以自動地有序執行。然而,這樣的自動觸發任務構建,上游任務只能對每個下游任務觸發一次。那么,當我們的quicktest任務構建完畢后,如何觸發多個slowtest任務構建呢 難道只能手工在網頁頁面上點擊“立即構建”嗎
當然不是。在Hudson任務設置里,如下圖,有這樣的一個設置,勾選并填寫”Authentication Token”上之后,我們就可以使用這個Token編寫腳本或程序來隨時觸發一個任務的構建了。
例如,用類似以下的Python代碼,就可以觸發一次”Your_Job”任務的一次構建。
如果”Your_Job”任務是帶參數(見后文)的,可以用類似以下的代碼觸發一次構建。
5.測試用例分配
為了讓slowtest任務的每一次構建能執行不同的自動化測試用例,我們需要指定該任務為帶參數的任務,在任務設置中勾選
并指定相應的參數。例如,我們指定一個字符串參數名為suite,用于指定某一次構建是運行哪一個suite里的case。這樣,在具體的某一次構建中,suite會以環境變量的方式存在。當然,如果構建的時候沒有指定suite參數,那么suite就會默認為None。
這樣,在一個任務的每次構建中,就可以根據環境變量suite的值去取不同的測試用例來運行了。
6.測試結果回收
當分布式測試執行完畢后,slowtest的測試結果仍然被拆分到了多個構建之中,如何把這些測試結果統一收集起來呢
例如,我們很可能需要把所有測試用例的運行生成的JUnit格式的測試結果報表合并在一起,即我們需要收集slowtest任務每一次構建所產生的xml測試結果文件。
解決辦法是,我們在slowtest任務里設置Hudson把我們需要的一些文件在構建完成后打包存檔起來。例如下圖這樣設置,則Hudson在每一次構建完成后,會將test_report文件夾下的所有xml文件上傳至服務器保存下來。
這樣,我們也就可以自己編寫腳本或程序去獲取這些文件了。例如,類似如下Python代碼,可以獲得test-slowtest任務第67次構建所生成的所有文件,打包保存為tmp.zip。
SQL注入攻擊是黑客攻擊網站最常用的手段。如果你的站點沒有使用嚴格的用戶輸入檢驗,那么常容易遭到SQL注入攻擊。SQL注入攻擊通常通過給站點
數據庫提交不良的數據或查詢語句來實現,很可能使數據庫中的紀錄遭到暴露,更改或被刪除。
為了防止SQL注入攻擊,PHP自帶一個功能可以對輸入的字符串進行處理,可以在較底層對輸入進行安全上的初步處理,也即Magic Quotes。(php.ini magic_quotes_gpc)。如果magic_quotes_gpc選項啟用,那么輸入的字符串中的單引號,雙引號和其它一些字符前將會被自動加 上反斜杠\。
但Magic Quotes并不是一個很通用的解決方案,沒能屏蔽所有有潛在危險的字符,并且在許多服務器上Magic Quotes并沒有被啟用。所以,我們還需要使用其它多種方法來防止SQL注入。
許多數據庫本身就提供這種輸入數據處理功能。例如PHP的
MySQL操作函數中有addslashes()、 mysql_real_escape_string()、mysql_escape_string()等函數,可將特殊字符和可能引起數據庫操作出錯的字 符轉義。那么這三個功能函數之間有什么卻別呢?下面我們就來詳細講述下。
雖然國內很多PHP程序員仍在依靠addslashes防止SQL注入,還是建議大家加強中文防止SQL注入的檢查。addslashes的問題在 于黑客 可以用0xbf27來代替單引號,而addslashes只是將0xbf27修改為0xbf5c27,成為一個有效的多字節字符,其中的0xbf5c仍會 被看作是單引號,所以addslashes無法成功攔截。
當然addslashes也不是毫無用處,它是用于單字節字符串的處理,多字節字符還是用mysql_real_escape_string吧。
另外對于php手冊中get_magic_quotes_gpc的舉例:
if (!get_magic_quotes_gpc()) { $lastname = addslashes($_POST[‘lastname’]); } else { $lastname = $_POST[‘lastname’]; } |
最好對magic_quotes_gpc已經開放的情況下,還是對$_POST[’lastname’]進行檢查一下。
再說下mysql_real_escape_string和mysql_escape_string這2個函數的區別:
mysql_real_escape_string 必須在(PHP 4 >= 4.3.0, PHP 5)的情況下才能使用。否則只能用 mysql_escape_string ,兩者的區別是:mysql_real_escape_string 考慮到連接的當前字符集,而mysql_escape_string 不考慮。
總結一下:
* addslashes() 是強行加\;
* mysql_real_escape_string() 會判斷字符集,但是對PHP版本有要求;
* mysql_escape_string不考慮連接的當前字符集。
dz中的防止sql注入就是用addslashes這個函數,同時在dthmlspecialchars這個函數中有進行一些替換$string = preg_replace('/&((#(\d{3,5}|x[a-fA-F0-9]{4}));)/', '&\\1',這個替換解決了注入的問題,同時也解決了中文亂碼的一些問題
本文總結一下平時經常使用的
SQL語句以及一些ORACLE函數的微妙之處。歡迎大家多多補充平時最常用的SQL語句,供大家
學習參考。
SQL> select * from temp2; NAME SORCE ---------- ---------- 1 43 2 23 3 42 4 87 5 12 <span style="font-size: 14px;"><strong><span style="color: #ff0000;">1、數據累加</span></strong></span> SQL> SELECT NAME, sum(sorce) OVER(ORDER BY NAME) 2 FROM temp2 3 ORDER BY NAME; NAME SUM(SORCE)OVER(ORDERBYNAME) ---------- --------------------------- 1 43 2 66 3 108 4 195 5 207 <span style="font-size: 14px;"><strong><span style="color: #ff0000;">2、去掉最大值和最小值</span></strong></span> SQL> SELECT NAME, 2 sorce, 3 LAG(sorce) over(order by sorce) Lag_List, 4 LEAD(sorce) over(order by sorce) Lead_List 5 FROM temp2; NAME SORCE Lag Lead ---------- ---------- ---------- ---------- 5 12 23 2 23 12 42 3 42 23 43 1 43 42 87 4 87 43 |
1、著名分析函數--排序
SQL> SELECT name, 2 value, 3 RANK() OVER(order by value) RANK_SORT, 4 DENSE_RANK() OVER(order by value) DENSE_SORT, 5 ROW_NUMBER() OVER(order by value) ROW_SORT 6 FROM sorce; NAME VALUE RANK_SORT DENSE_SORT ROW_SORT ---------- ------ ---------- ---------- ---------- wu 21 1 1 1 zhang 60 2 2 2 Li 70 3 3 3 xue 119 5 5 5 <span style="color: #ff0000;">wang 130 6 6 6 chen 130 6 6 7 sun 175 8 7 8</span> zhao 285 9 8 9 su 359 10 9 10 Li 480 11 10 11<br> |
可見三者的區別:<br>RANK()OVER():如果值相同,則兩者順序號相同,隨機一個在另外一個的上邊,而且順序號會有間斷,不是連續的;<br>DENSE_RANK():如果值相同,則兩者順序號相同,隨機一個在另外一個的上邊,而且順序號仍然是連續的,不存在斷層的現象;<br>ROW_NUMBER():如果值相同,則兩種順序號不同,安裝順序號依次排開,而且順序號是連續的。
2、TRANSLATE()函數
translate函數與replace類似,但是又與replace不同,translate指定字符串string中出現的from_str,將from_str中各個字符替換成to_str中位置順序與其相同的to_str中的字符。
SQL Reference中給的例子:SELECT TRANSLATE('SQL*Plus User''s Guide', ' */''', '___') FROM DUAL;
巧用:
?。?)判斷一個字符串是數字
SELECT TRANSLATE('ABC123','#1234567890.','#') FROM DUAL;
?。?)統計字符E出現的次數
SELECT LENGTHB(TRANSLATE('ABCDEFGEFGDBE','E'||'ABCDEFGEFGDBE','E')) FROM DUAL;
3、ROUND()函數
我們平時用得最多的是第一種,用ROUND()函數作為數據四舍五入運算,其實ROUND函數還有第二種形式,對日期進行格式化操作,與TRUNC()函數類似。
如:SELECT ROUND(SYSDATE,'yyyy') FROM DUAL;
SELECT ROUND(SYSDATE,'MM') FROM DUAL;
SELECT ROUND(SYSDATE,'HH24') FROM DUAL;
4、NVL相關函數
NVL相關的函數有:NVL(expr1,expr2),NVL2(expr1,expr2,expr3),NULLIF(expr1,expr2),DECODE(expr1,expr2,value1,expr3,value2...,default)
(1) NVL(expr1,expr2) :如果expr1為空,則用expr2來替換。
(2) NVL2(expr1,expr2,expr3) :如果expr1非空,則返回expr2,否則返回expr3。
(3) NULLIF(expr1,expr2):將expr1和expr2做比較,如果想等,則返回null,否則返回expr1。
(3) DECODE(expr1,expr2,value1,expr3,value2...,default):如果expr1與expr2相等,則返回value1,如果expr1與expr3相等,則返回value2,...否則,返回default。
5、收集表的統計信息
收集表的統計信息方法有很多種: (1) ANALYZE (2) DBMS_STATS
看起來很繁瑣,其實用起來挺簡單的。
如對某張表進行分析:
ANALYZE TABLE TABLE_NAME COMPUTE STATISTICS;
目前,ORACLE官方推薦第二種方法。在DBMS_STATS包里有很多過程和方法,對SCHEMA、TABLE和INDEX進行收集統計信息相關的操作。
EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'SCOTT',TABNAME=>'EMP',DEGREE=>4,CASCADE=>'TRUE');
一、JSON
JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。 JSON采用完全獨立于語言的文本格式。這些特性使JSON成為理想的數據交換語言。易于人閱讀和編寫,同時也易于機器解析和生成。
JSON與XML的對比(引用自:sanpintian的CSDN博客):
1、可讀性:JSON和XML的可讀性可謂不相上下,一邊是建議的語法,一邊是規范的標簽形式,很難分出勝負。
2、可擴展性:XML天生有很好的擴展性,JSON當然也有,沒有什么是XML能擴展,JSON不能的。
3、編碼難度:XML有豐富的編碼工具,比如Dom4j、JDom等,JSON也有json.org提供的工具,但是JSON的編碼明顯比XML容易許多,即使不借助工具也能寫出JSON的代碼,可是要寫好XML就不太容易了。
4、解碼難度:XML的解析得考慮子節點父節點,讓人頭昏眼花,而JSON的解析難度幾乎為0。這一點XML輸的真是沒話說。
5、流行度:XML已經被業界廣泛的使用,而JSON才剛剛開始,但是在Ajax這個特定的領域,未來的發展一定是XML讓位于JSON。到時Ajax應該變成Ajaj(Asynchronous Javascript and JSON)了。
二、導包
使用JSON需要導入以下包:
commons-beanutils.jar
commons-logging.jar
commons-lang.jar
commons-collection.jar
ezmorph.jar
json-lib.jar
三、實現
Book類的實現:
1 public class Book { 2 private String name; 3 private double price; 4 5 public String getName() { 6 return name; 7 } 8 9 public void setName(String name) { 10 this.name = name; 11 } 12 13 public double getPrice() { 14 return price; 15 } 16 17 public void setPrice(double price) { 18 this.price = price; 19 } 20 21 @Override 22 public String toString() { 23 return name+" "+price; 24 } 25 } |
1 /** 2 * @author ZWQ 3 * **/ 4 public class JsonTest { 5 public static void main(String[] args) { 6 //*********************************************************************** 7 // json基本測試 8 { 9 //新建一個JSON數組 10 JSONArray jsonArray = new JSONArray(); 11 //新建一個JSON對象 12 JSONObject json1 = new JSONObject(); 13 json1.put("id", "1"); 14 json1.put("name", "張三"); 15 json1.put("password", "123456"); 16 //將JSON對象添加到JSON數組中去 17 jsonArray.add(json1); 18 19 JSONObject json2 = new JSONObject(); 20 json2.put("id", "2"); 21 json2.put("name", "李四"); 22 json2.put("password", "654321"); 23 jsonArray.add(json2); 24 System.out.println("json數組基本測試:" + jsonArray); 25 26 //結果: 27 //[{"id":"1","name":"張三","password":"123456"},{"id":"2","name":"李四","password":"654321"}] 28 } 29 30 //*********************************************************************** 31 //將對象轉成JSON字符串 32 { 33 Book book = new Book(); 34 book.setName("Java入門教程"); 35 book.setPrice(52.3); 36 //將Java對象轉成JSON對象 37 JSONObject jsonObject = JSONObject.fromObject(book); 38 System.out.println("從Object到JSONObject:" + jsonObject.toString()); 39 40 //結果: 41 //從Object到JSONObject:{"name":"Java入門教程","price":52.3} 42 } 43 44 //*********************************************************************** 45 //將對象集合轉成JSON字符串 46 { 47 List<Book> list = new ArrayList<Book>(); 48 Book book1 = new Book(); 49 book1.setName("高等數學I"); 50 book1.setPrice(34.1); 51 Book book2 = new Book(); 52 book2.setName("線性代數"); 53 book2.setPrice(12.7); 54 list.add(book1); 55 list.add(book2); 56 //將List集合轉為JSON數組 57 JSONArray jsonArray= JSONArray.fromObject(list); 58 System.out.println("從Object集合到JSONArray:" + jsonArray.toString()); 59 60 //結果: 61 //從Object集合到JSONArray:[{"name":"高等數學I","price":34.1},{"name":"線性代數","price":12.7}] 62 } 63 64 //*********************************************************************** 65 // 將JSON字符串轉為Java對象 66 { 67 String jsonString = "{name:'數據結構',price:52.3}"; 68 JSONObject jsonObject = JSONObject.fromObject(jsonString); 69 //將JSON對象轉為Java對象 70 Book book = (Book) JSONObject.toBean(jsonObject, Book.class); 71 System.out.println(book.toString()); 72 73 //結果: 74 //數據結構 52.3 75 } 76 77 //*********************************************************************** 78 //將JSON字符串轉為Java對象數組 79 { 80 // (2).Bean的數組 81 String jsonsString = "[{name:'數據庫基礎',price:52.3},{name:'Oracle 11g精華',price:42.3}]"; 82 JSONArray jsonArray = JSONArray.fromObject(jsonsString); 83 //將JSON數組轉為Java對象數組 84 Book[] books = (Book[]) JSONArray.toArray(jsonArray, Book.class); 85 for (Book b : books) { 86 System.out.println(b.toString()); 87 } 88 89 //結果: 90 //數據庫基礎 52.3 91 //Oracle 11g精華 42.3 92 } 93 } 94 } |
四、前端解析
1 //Jquery提供的獲取json的方法 2 //使用前先導入Jquery 3 4 $('#button').click(function(){ 5 //url:請求的地址 6 $.getJSON('url', { 7 //id是需要傳的參數 8 id: 1 9 }, function(data) {//成功后data即為獲取的json字符串 10 //例如data:[{"name":"高等數學I","price":34.1},{"name":"線性代數","price":12.7}] 11 alert("第二本書是:"+data[1].name+" 價格是:"+data[1].price); 12 }); 13 }); |
TestLink作為開源
測試管理工具,可以進行測試工程、測試計劃以及執行計劃的管理,而且TestLink團隊提供了XML-PRC的接口供第三方工具調用,接口支持程度也比較好。
Fitnesse作為開源驗收測試框架,本身可以做到測試集、
測試用例的執行,有較為優秀的測試執行行為的管理以及測試結果的收集。
由于Testlink大部分場合下是用于手工測試用例的管理,為了能夠是Testlink對于測試用例管理的優點也用于Fitnesse上
自動化測試用例的管理,也為了能夠讓手工測試用例和自動化回歸測試用例mapping起來,方便測試管理者能夠清晰知道自動化測試用例在測試項目中的比例,也為了測試管理者可以較好的管理回歸測試流程,考慮將Fitnesse和Testlink進行集成。
兩個平臺集成的基本思路是: 1. 將Testlink上的用例和Fitnesse上的用例一一mapping. 2. 將Fitnesse上用例的執行結果能夠實時反饋給Testlink上用例的執行結果。
Testlink Java api client提供了一個非常好的接口,
reportTestCaseResult(projectName,testPlanName,testCaseNameOrVisiableID,buildName,execNotes,testResultStatus)
該接口有6個參數,其中
projectName: Testlink上對應的測試工程名稱
testPlanName:Testlink上測試工程對應的測試計劃
testCaseNameOrVisiableID: Testlink上測試用例的名稱或ID,這里的ID是指測試項目前綴加上'-'在加上阿拉伯數字
buildName:Testlink上對應測試計劃的構建執行計劃
execNotes:是指每個case執行后的備注,可以為null
testResultStatus:是指測試用例執行結果,'p'或者'f'
通過調用給接口,我們可以完成測試用例執行結果的傳遞。
接下去我們要解析Fitnesse執行結果的分析:
在這里我通過一個代理proxy來完成該任務,該代理需要完成Fitnesse測試執行結果的解析,測試用例ID的解析,然后完成TestLink接口的調用
如下圖所示總體架構: