1、漏洞總數
AppScan Source:91
Fortify:121
2、Disclaimer.htm:34(Cross-Site Scripting:DOM)的漏洞Fortify能掃描出來,AppScan Source掃描不出來
另外,Fortify能掃描出比較多Persistent類型的XSS漏洞
并且歸類比較好(分DOM、Persistent、Reflected類型列出)
3、AdminLoginServlet.java:35(Password Management:Hardcoded Password)的漏洞Fortify能掃描出來,AppScan Source掃描不出來
4、Fortify掃出的DBUtil.java:238(Access Control:Database)在AppScan中被歸類到
SQL Injection
5、admin.jsp:18(Password Management:Empty Password)屬于誤報
<script language="javascript">
function confirmpass(myform)
{
if (myform.password1.value.length && (myform.password1.value==myform.password2.value))
{
return true;
}
else
{
myform.password1.value="";
myform.password2.value="";
myform.password1.focus();
alert ("Passwords do not match");
return false;
}
}
</script>
6、Fortify會報比較多這類問題:
Code Correctness:Class Does Not Implement equals
Hardcoded Domain in HTML
Hidden Field
J2EE Bad Practices
J2EE Misconfiguration
Missing Check against Null
Password Management:Password in Comment
Poor Error Handling
System Information Leak:Incomplete Servlet Error Handling
7、Fortify會報比較多transfer.jsp:32(Cross-Site Request Forgery)這類CSRF的問題,而AppScan Source沒有掃出來
8、Fortify有掃出ServletUtil.java(Missing XML Validation)的問題,而AppScan Source沒有掃出來
9、Fortify有掃出AdminServlet.java:65(Redundant Null Check)的問題,而AppScan Source沒有掃出來
單元測試是開發者編寫的一小段代碼,用于檢驗被測代碼的一個很小的、很明確的功能是否正確。
單元測試目的?
執行單元測試,是為了證明某段代碼的行為確實和開發者所期望的一致。
1 測試目的,一個是測試程序的整體邏輯,另一個是測試程序中一個獨立的模塊
2 通常的執行人員不一樣,白盒一般是由專門的白盒測試人員完成,單元測試一般由程序員自己完
計劃你的單元測試:
設計一系列的輸入和預期結果
Eclipse中使用Junit:
eclipse中已經內置Junit,無需自己再安裝
選擇一個需要單元測試的工程,右鍵點擊Properties
添加Junit依賴
選擇Junit
每一個軟件項目,不管是project類項目,還是產品類項目,都必須經歷需求分析、系統設計、編碼實現、集成測試、部署、交付、維護和支持的過程。在這個過程中,將生成各種各樣不同的工件,包含文檔、源程序、可執行代碼、支持庫。更可怕的是,頻繁出現的變更是不可避免的,因此面向如此龐大且不斷變動的信息集,怎樣使其有序、高效地存放、查找和利用就成為了一個突出的問題。
針對這一問題,最早的開發者嘗試過的解決的方法是通過手工來實現:
1)文檔:每次改動時都另存為一個新的文件,然后通過文件名稱進行區分,比如 "XXX 軟件需求說明書V1.0, XXX軟件需求說明書V1.1, XXX 軟件需求說明書V2.0.",并且在文件里注明每次版本號變化的內容;
2) 源碼:每次要改動時就將整個project文件夾復制一份,將原來的文件夾進行改名,比如 "XX 項目V1.0、 XX 項目1.01、 .",然后在新的文件夾中進行改動;
可是這樣的方法,不僅十分繁瑣,easy出錯,并且會帶來大量的垃圾數據。假設是團隊協同開發或者是項目規模較大時,還是會造成非常大的混亂。非常顯然,這樣簡陋的方法是無法應對這一問題的。
后來,有人嘗試從制造工業領域引入了"
配置管理 "這一概念,通過不懈的研究與實踐,終于形成了一套管理辦法和活動原則,這也就是軟件配置管理。
通過軟件配置管理,將對軟件系統中的多重版本號實施系統的管理;全面記載系統開發的歷史過程,包含為什么改動,誰作了改動,改動了什么;管理和追蹤開發過程中危害軟件質量以及影響開發周期的缺陷和變化。并對開發過程進行有效地管理和控制,完整、明白地記載開發過程中的歷史變更,形成規范化的文檔,不僅使日后的維護和升級得到保證,并且更重要的是,這還會保護寶貴的代碼資源,積累軟件財富,提高軟件重用率,加快投資回報。
常見的配置管理工具
正如前面所述,因為軟件配置管理過程十分繁雜,管理對象錯綜復雜,假設是採用人工的辦法不僅費時費力,還easy出錯,產生大量的廢品。因此,引入一些自己主動化工具是十分有裨益的,這也是做好配置管理的必要條件。
正是因為如此,市場上出現了大量的自己主動化配置管理工具,這些工具的實現原理與基本機制均十分接近,但因為其定位不同,因此各有特點,下面我們就對一些常見的配置管理工具做一簡單的介紹。
元老:CCC 、SCCS、 RCS
上個世紀七十年代初期加利福利亞大學的Leon Presser 教授撰寫了一篇論文,提出控制變更和配置的概念,之后在1975年,他成立了一家名為 SoftTool的公司,開發了自己的配置管理工具:CCC,這也是最早的配置管理工具之中的一個。
在軟件配置管理工具發展史上,繼CCC之后,最具有里程碑式的是兩個自由軟件: Marc Rochkind 的SCCS (Source Code Control System) 和 Walter Tichy 的RCS (Revision Control System),它們對配置管理工具的發展做出了重大的貢獻,直到如今絕大多數配置管理工具基本上都源于它們的設計思想和體系架構。
Rational 公司是全球最大的軟件CASE 工具提供商,現已被
IBM 收購。或許是受到其拳頭產品、可視化建模第一工具Rose 的影響,它開發的配置管理工具ClearCase 也是深受用戶的喜愛,是如今應用面最廣的企業級、跨平臺的配置管理工具之中的一個。
ClearCase提供了比較全面的配置管理支持,當中包含版本號控制、
工作 空間管理、Build管理等,并且開發者無需針對其改變現有的環境、工具和工作方式。
其最大的缺點就在于其價格不菲,每一個client用戶許可證大約須要幾千美金,所以在國內應用群體有限。
1) 版本號控制
ClearCase 不僅能夠對文件、文件夾、鏈接進行版本號控制,同一時候還提供了先進的版本號分支和歸本功能用于支持并行開發。另外,它還支持廣泛的文件類型。
2)工作空間管理
能夠為開發者提供私人存儲區,同一時候能夠實現成員之間的信息共享,從而為每一位開發者提供一致、靈活、可重用的工作空間域。
3) Build管理
對ClearCase 控制的數據,既能夠使用定制腳本,也可使用本機提供的make 程序。
其最大的缺點就在于其價格不菲,每一個client用戶許可證大約須要幾千美金,所以在國內應用群體有限。
新秀:Hansky Firefly
做為Hansky公司
軟件開發 管理套件中重要一員的Firefly,能夠輕松管理、維護整個企業的軟件資產,包含程序代碼和相關文檔。 Firefly是一個功能完好、執行速度極快的軟件配置管理系統,能夠支持不同的
操作系統 和多種集成開發環境,因此它能在整個企業中的不同團隊,不同項目中得以應用。
Firefly基于真正的客戶機/
server 體系結構,不依賴于不論什么特殊的網絡文件系統,能夠平滑地執行在不同的LAN、WAN 環境中。它的安裝配置過程簡單易用,Firefly 能夠自己主動、安全地保存代碼的每一次變化內容,避免代碼被無意中覆蓋、改動。
項目管理 人員使用 Firefly能夠有效地組織開發力量進行并行開發和管理項目中各階段點的各種資源,使得產品公布易于管理;并能夠高速地回溯到任一歷史版本號。系統管理員使用Firefly 的內置工具能夠方便的進行存儲庫的備份和恢復,而不依賴于不論什么第三方工具。
開源奇葩: CVS
CVS 是Concurrent Versions System 的縮寫,它是開放源碼軟件世界的一個偉大杰作,因為其簡單易用、功能強大,跨平臺,支持并發版本號控制,并且免費,它在全球中小型軟件企業中得到了廣泛使用。
其最大的遺憾就是缺少對應的技術支持,很多問題的解決須要自已尋找資料,甚至是讀源碼。
小工作組級:Merant PVCS
MERANT 公司的 PVCS 能夠提供對軟件配置管理的基本支持,通過使用其圖形界面或相似SCCS 的命令,能夠基本滿足小型項目開發的配置管理需求。 PVCS 盡管功能上也基本能夠滿足需求,可是其性能表現一直較差,逐漸地被市場所冷落。
入門級:Microsoft Visual Source Safe
Visual Source Safe,即VSS ,是
微軟 公司為Visual Studio配套開發的一個小型的配置管理工具,準確來說,它僅能夠稱得上是一個小型的版本號控制軟件。 VSS的優點在于其與Visual Studio實現了無縫集成,使用簡單。提供了歷史版本號記錄、改動控制、文件比較、日志等基本功能。
但其缺點也是十分明顯的,僅僅支持
Windows 平臺,不支持并行開發,通過 Check out - Modify - Check in的管理方式,一個時間僅僅同意一個人改動代碼,并且速度慢、伸縮性差,不支持異地開發。甚至于微軟本身也不採用其做為配置管理工具,而是使用一個名為SLM 的內部工具。
English »
Afrikaans Albanian Arabic Armenian Azerbaijani Basque Bengali Belarusian Bulgarian Catalan Chinese (Simp) Chinese (Trad) Croatian Czech Danish Dutch English Esperanto Estonian Filipino Finnish French Galician Georgian German Greek Gujarati Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Kannada Korean Lao Latin Latvian Lithuanian Macedonian Malay Maltese Norwegian Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Tamil Telugu Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish
怎樣選擇配置管理工具
面對這些形形色色,各有千秋的配置管理工具,怎樣依據組織特點、開發團隊須要,選擇切合適用的工具呢?筆者就結合工作實踐中的經驗與大家做一些交流與探討。
配置管理工具的選擇所需考慮的因素大體包含下面幾個因素:
功能是否符合實際需求?是否符合團隊特點?性能是否愜意?費用能否夠接受?售后服務怎樣?接下來,我們就這幾方面逐一深入地探討:
1)功能是否符合實際需求,是否符合團隊特點
工具就是用來幫助您解決這個問題的,因此功能是否符合實際需求是最重要的推斷因素。而大多數主流配置管理工具的基本功能都能夠滿足,因此主要須要推斷下面幾個因素:
并行開發支持
在團隊協作開發過程中,有兩種基本的模式:集體代碼權和個體代碼權。採用集體代碼權模式進行開發時,一段代碼可能同一時候會被多個開發者同一時候改動;而採用個體代碼權模式進行開發時,每一段代碼都始終被一個開發者獨享,別人須要改動時也會通過該開發者完畢。
而配置管理軟件針對這一情況,也採用了不同的策略:Copy-Modify-Merge(拷貝、改動、合并 ) 的并行開發模式、Check out-Modify-Check in(簽出、改動、簽入)的獨占開發模式。在并行開發模式下,開發者能夠并行開發、更改代碼, Firefly會自己主動檢測到代碼沖突,并自己主動合并,或提示開發者手動解決。
表一、并行開發支持比較表
工具名稱
說明
ClearCase
Copy-Modify-Merge 模式
Firefly
Copy-Modify-Merge 模式
CVS
Copy-Modify-Merge 模式
PVCS
Check out-Modify-Check in 模式
VSS
Check out-Modify-Check in 模式
異地開發支持
假設你的開發團隊分布在不同的開發地點,就須要對工具的異地開發功能進行細致的評估了。大多數工具都提供基于 Web的界面,用戶能夠通過瀏覽器執行配置管理的相關操作,并且有些工具就通過這樣的方法來實現對異地開發的支持。
這樣的實現方法有太多的局限性,比如網絡(Internet)連接帶寬的限制、防火墻以及安全問題等。真正意義上的異地開發支持,是指在不同的開發地點建立各自的存儲庫,通過工具提供同步功能自己主動或手動同步。這樣做的優點是與網絡無關,即便各個開發地點之間沒有實時連通的網絡,也能夠通過 E-Mail 附件等其他方式將同步包發給對方,實現手動的同步。
表二異地開發支持比較表
工具名稱
說明
ClearCase
提供MultiSite 模塊,通過自己主動或手動同步位于不同開發地點的存儲庫的方式,支持異地開發
Firefly
提供ServerSync 模塊,通過自己主動或手動同步位于不同開發地點的存儲庫的方式,支持異地開發
CVS
無專門支持的模塊
PVCS
無專門支持的模塊
VSS
無專門支持的模塊
值得說明的是,在不同開發點建立各自存儲庫的方式,主要適用于兩個或兩個以上位于不同地點的開發團隊協作開發的情況。假設僅是採用虛擬團隊合作的方式,開發者以個體的形式散落在不同地方,則更適合通過 Internet 直接操作遠程的配置管理server。
跨平臺開發支持
假設企業須要從事多個不同平臺下的開發工作,就須要配置管理工具能夠對跨平臺開發提供支持,否則勢必會給開發、測試、公布等各個環節帶來不便,將使大量的時間被浪費于代碼的手工上傳、下載中。
表三跨平臺開發支持比較表
工具名稱
說明
ClearCase
支持常見的平臺
Firefly
軟件本身基于Java開發,可在 Windows、Linux、 Solaris、HP-UX、 AIX等常見平臺上使用,平臺之間的移植也非常方便
CVS
支持差點兒全部的操作系統
PVCS
軟件本身基于Java 開發,能夠支持常見的平臺
VSS
僅支持Windows 操作系統
與開發工具的集成性
配置管理工具與開發工具是編碼過程中最經常使用到兩種工具,因此它們之間的集成性直接影響到開發者的便利性,假設無法良好集成,開發者將不可避免地在配置管理工具與開發工具之間來回切換。
表四與開發工具集成性比較表
工具名稱
說明
ClearCase
直接與資源管理器集成,十分易用
Firefly
與常見開發工具無縫集成
CVS
對開發工具集成性較差
PVCS
僅支持Windows 操作系統
VSS
與Visual Studio開發工具包無縫連接,其他開發工具集成性差
2)性能是否愜意
配置管理工具軟件的一些性能指標對于終于的選擇也有著至關重要的影響。
執行性能
假設開發團隊規模不大的情況下,配置管理工具軟件的性能不會造成非常大影響,但假設項目規模比較大,團隊成員逐漸增多的情況下,其執行性能就會帶來非常大的影響。
表五執行性能比較表
工具名稱
說明
ClearCase
server採用多進程機制,使用自帶多版本號文件系統MVFS,對性能有較大負面影響。做為一款企業級、全面的開發配置管理工具,適用于大型開發團隊
Firefly
server採用了多線程的應用server,性能表現優秀,做為一款企業級、全面的開發配置管理,能適用于50人到上千人的團隊
CVS
較高的執行性能,適用于各種級別的開發團隊
PVCS
server採用文件系統共享方式,對CPU、內存及網絡要求較高,性能一般,僅適用于中小型項目團隊,不適合于企業級應用
VSS
相對功能單一、簡陋,適用于幾個人的小型團隊,在數據量不大的情況下,性能能夠接受
易用性
表六易用性比較表
工具名稱
說明
ClearCase
安裝、配置、使用相對較復雜,須要進行團隊培訓
Firefly
在提供全面配置管理功能的情況下,安裝、配置、使用較為簡單,包含安裝、配置、培訓在內的整個實施周期一般不會超過一個月。
CVS
安裝、配置較復雜,但使用比較簡單,僅僅需對配置管理做簡單培訓就可以
PVCS
使用比較簡單,僅僅需對配置管理做簡單培訓就可以
VSS
安裝、配置、使用均較簡單,非常easy上手使用
從用戶界面、與開發工具的集成性角度來說,這幾款主流的配置管理軟件均有較好的設計,均有較好的易用性。
安全性
表七安全性比較表
工具名稱
說明
ClearCase
採用C/S模式,須要共享server上的存儲文件夾以供client訪問,這將帶來一定安全隱患
Firefly
server上的存儲文件夾不用共享,對client不透明,client不可直接訪問存儲文件夾,使系統更安全可靠
CVS
採用C/S 模式,不須要共享server上的存儲文件夾,安全性較好
PVCS
基于文件系統共享,并且須要以"可寫 "的權限共享存儲文件夾,存在較大的安全隱患
VSS
基于文件系統共享實現對server的訪問,須要共享存儲文件夾,這將帶來一定安全隱患
3)費用能否夠接受
Rational ClearCase 、Hansky Firefly 兩款均屬于企業級配置管理工具軟件 ,ClearCase價格較貴,,相比之下 Hansky Firefly 是一款不錯的選擇。
而 PVCS其價格大約是每client幾百美元的水平,對于國內企業來說,性價比不太劃算。 VSS 是微軟打包在Visual Studio開發工具包之中的,顯然花費的精力不大,價格也比較廉價,能夠做為個人、小項目團隊版本號控制之用。
而 CVS則是一款全然免費的開源軟件,性能較之企業級配置管理工具差距不大,也是一種不錯的選擇。
4) 售后服務怎樣
表八售后服務比較表
工具名稱
說明
ClearCase
大型商用軟件,已被IBM公司收購,但國內市場拓展有限,因此服務支持會受到限制。如今中國用戶的支持是由位于澳大利亞悉尼的支持中心聯系
Firefly
大型商用軟件,已在中國成立分公司,全面拓展市場之中,在北京設有支持中心
CVS
做為開源軟件,無官方支持,須要用戶自己查找資料解決技術問題,如今也出現專門為CVS 做技術支持的公司
PVCS
在中國市場開拓有限,國內沒有支持中心
VSS
做為微軟的非核心產品,技術支持有限。在其站點上有提供一些常見問題,僅僅有對正式購買的用戶提供一定的技術支持
售后服務與產品支持也是一個非常重要的考察點,工具在使用過程中出現這樣那樣的問題是非常尋常的事,有些是因為使用不當,有些則是工具本身的缺陷。這些問題都會直接影響到開發團隊的使用,因此隨時能夠找到專業技術人員解決這些問題就變成十分重要。
實例說明
最后,筆者介紹幾個實際的案例,希望對大家選擇軟件配置管理工具軟件有幫助。
案例一
某公司擁有10 名專職開發者以及一些兼職的開發者,主要從事 Windows和Linux 平臺下的軟件開發,採用的工具包含Visual Studio 系列、 GCC 等。為了能夠加強版本號控制與配置管理工作,決定引入一些自己主動化配置管理工具。
經過謹慎的選擇,採用了兩步走的方法:
1) 首先採用了Visual Studio 軟件包中的 VSS做為配置管理工具;
<SPAN style="FONT-SIZE: 9pt;"word-break: break-all; line-height: 21.6000003814697px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;"> ...
一般來說,維護需求的項目時間都是比較緊急的,維護嘛,用戶等著上線用的啊,其實在這里,我們對維護需求和新增需求的定義都不太清晰。
怎么理解呢?我個人的理解:
維護需求,是指用戶提出在系統使用過程中的問題以及整合目前用戶覺得需要改進系統的一些功能的需求文檔。
新增需求,就是指用戶在不滿足當前系統使用功能的前提下提出一些不包含之前的需求文檔內的新增的功能而形成的需求文檔,它沒有包含用戶繼續解決的用戶bug。
因此,我個人從定義上區分,維護需求多數只是針對用戶問題去修復并驗證bug,當然也有摻入一些用戶界面體驗、新增的小功能點吧。而新增需求,在項目開發中可能就不是一個小新增功能點了,更多的是大的項目系統分支、功能模塊,需求業務規則的編寫程度需要更明細。
為什么要創建索引呢?這是由于,創建索引能夠大大提高系統的性能。
第一,通過創建唯一性索引,能夠保證
數據庫 表中每一行數據的唯一性。
第二,能夠大大加快 數據的檢索速度,這也是創建索引的最基本的原因。
第三,能夠加速表和表之間的連接,特別是在實現數據的參考完整性方面特別有意義。
第四,在使用分組和排序 子句進行數據檢索時,相同能夠顯著降低查詢中分組和排序的時間。
第五,通過使用索引,能夠在查詢的過程中,使用優化隱藏器,提高系統的性能。
或許會有人要問:添加索引有如此多的長處,為什么不正確表中的每個列創建一個索引呢?這樣的想法固然有其合理性,然而也有其片面性。盡管,索引有很多長處, 可是,為表中的每個列都添加索引,是很不明智的。這是由于,添加索引也有很多不利的一個方面。
第一,創建索引和維護索引要耗費時間,這樣的時間隨著數據 量的添加而添加。
第二,索引須要占物理空間,除了數據表占數據空間之外,每個索引還要占一定的物理空間,假設要建立聚簇索引,那么須要的空間就會更大。
第三,當對表中的數據進行添加、刪除和改動的時候,索引也要動態的維護,這樣就減少了數據的維護速度。
索引是建立在數據庫表中的某些列的上面。因此,在創建索引的時候,應該細致考慮在哪些列上能夠創建索引,在哪些列上不能創建索引。一般來說,應該在這些列 上創建索引,比如:
在常常須要搜索的列上,能夠加快搜索的速度;
在作為主鍵的列上,強制該列的唯一性和組織表中數據的排列結構;
在常常常使用在連接的列上,這 些列主要是一些外鍵,能夠加快連接的速度;
在常常須要依據范圍進行搜索的列上創建索引,由于索引已經排序,其指定的范圍是連續的;
在常常須要排序的列上創 建索引,由于索引已經排序,這樣查詢能夠利用索引的排序,加快排序查詢時間;
在常常使用在WHERE子句中的列上面創建索引,加快條件的推斷速度。
相同,對于有些列不應該創建索引。一般來說,不應該創建索引的的這些列具有下列特點:
第一,對于那些在查詢中非常少使用或者參考的列不應該創建索引。這是因 為,既然這些列非常少使用到,因此有索引或者無索引,并不能提高查詢速度。相反,由于添加了索引,反而減少了系統的維護速度和增大了空間需求。
第二,對于那 些僅僅有非常少數據值的列也不應該添加索引。這是由于,由于這些列的取值非常少,比如人事表的性別列,在查詢的結果中,結果集的數據行占了表中數據行的非常大比 例,即須要在表中搜索的數據行的比例非常大。添加索引,并不能明顯加快檢索速度。
第三,對于那些定義為text, image和bit數據類型的列不應該添加索引。這是由于,這些列的數據量要么相當大,要么取值非常少。
第四,當改動性能遠遠大于檢索性能時,不應該創建索 引。這是由于,改動性能和檢索性能是互相矛盾的。當添加索引時,會提高檢索性能,可是會減少改動性能。當減少索引時,會提高改動性能,減少檢索性能。因 此,當改動性能遠遠大于檢索性能時,不應該創建索引。
創建索引的方法和索引的特征
創建索引的方法
創建索引有多種方法,這些方法包含直接創建索引的方法和間接創建索引的方法。直接創建索引,比如使用CREATE INDEX語句或者使用創建索引向導,間接創建索引,比如在表中定義主鍵約束或者唯一性鍵約束時,同一時候也創建了索引。盡管,這兩種方法都能夠創建索引,但 是,它們創建索引的詳細內容是有差別的。
使用CREATE INDEX語句或者使用創建索引向導來創建索引,這是最主要的索引創建方式,而且這樣的方法最具有柔性,能夠定制創建出符合自己須要的索引。在使用這樣的方式 創建索引時,能夠使用很多選項,比如指定數據頁的充滿度、進行排序、整理統計信息等,這樣能夠優化索引。使用這樣的方法,能夠指定索引的類型、唯一性和復合 性,也就是說,既能夠創建聚簇索引,也能夠創建非聚簇索引,既能夠在一個列上創建索引,也能夠在兩個或者兩個以上的列上創建索引。
通過定義主鍵約束或者唯一性鍵約束,也能夠間接創建索引。主鍵約束是一種保持數據完整性的邏輯,它限制表中的記錄有相同的主鍵記錄。在創建主鍵約束時,系 統自己主動創建了一個唯一性的聚簇索引。盡管,在邏輯上,主鍵約束是一種重要的結構,可是,在物理結構上,與主鍵約束相相應的結構是唯一性的聚簇索引。換句話 說,在物理實現上,不存在主鍵約束,而僅僅存在唯一性的聚簇索引。相同,在創建唯一性鍵約束時,也同一時候創建了索引,這樣的索引則是唯一性的非聚簇索引。因此, 當使用約束創建索引時,索引的類型和特征基本上都已經確定了,由用戶定制的余地比較小。
當在表上定義主鍵或者唯一性鍵約束時,假設表中已經有了使用CREATE INDEX語句創建的標準索引時,那么主鍵約束或者唯一性鍵約束創建的索引覆蓋曾經創建的標準索引。也就是說,主鍵約束或者唯一性鍵約束創建的索引的優先 級高于使用CREATE INDEX語句創建的索引。
索引的特征
索引有兩個特征,即唯一性索引和復合索引。
唯一性索引保證在索引列中的所有數據是唯一的,不會包括冗余數據。假設表中已經有一個主鍵約束或者唯一性鍵約束,那么當創建表或者改動表時,SQL Server自己主動創建一個唯一性索引。然而,假設必須保證唯一性,那么應該創建主鍵約束或者唯一性鍵約束,而不是創建一個唯一性索引。當創建唯一性索引 時,應該認真考慮這些規則:當在表中創建主鍵約束或者唯一性鍵約束時,SQL Server自己主動創建一個唯一性索引;假設表中已經包括有數據,那么當創建索引時,SQL Server檢查表中已有數據的冗余性;每當使用插入語句插入數據或者使用改動語句改動數據時,SQL Server檢查數據的冗余性:假設有冗余值,那么SQL Server取消該語句的運行,而且返回一個錯誤消息;確保表中的每一行數據都有一個唯一值,這樣能夠確保每個實體都能夠唯一確認;僅僅能在能夠保證實體 完整性的列上創建唯一性索引,比如,不能在人事表中的姓名列上創建唯一性索引,由于人們能夠有同樣的姓名。
復合索引就是一個索引創建在兩個列或者多個列上。在搜索時,當兩個或者多個列作為一個關鍵值時,最好在這些列上創建復合索引。當創建復合索引時,應該考慮 這些規則:最多能夠把16個列合并成一個單獨的復合索引,構成復合索引的列的總長度不能超過900字節,也就是說復合列的長度不能太長;在復合索引中,所 有的列必須來自同一個表中,不能跨表建立復合列;在復合索引中,列的排列順序是很重要的,因此要認真排列列的順序,原則上,應該首先定義最唯一的列,例 如在(COL1,COL2)上的索引與在(COL2,COL1)上的索引是不同樣的,由于兩個索引的列的順序不同;為了使查詢優化器使用復合索引,查詢語 句中的WHERE子句必須參考復合索引中第一個列;當表中有多個關鍵列時,復合索引是很實用的;使用復合索引能夠提高查詢性能,降低在一個表中所創建的 索引數量。
無論缺陷預防
工作 貫徹落實地多好,軟件組件總有缺陷。這很明顯,因為開發商無法阻止/消除
軟件開發 周期的所有缺陷。因此,軟件必須進行徹底的
測試 ,然后才交付給最終用戶。測試人員的責任是:設計既可以(ⅰ)找軟件缺陷,又能(ii )評估該軟件的性能,可用性和可靠性等方面的測試。
現在,為了實現這些目標,測試人員必須(往往是從一個非常大的執行域中)選擇和/或制定
測試用例 的有限數量。不幸的是,完整的測試通常不是在這個范圍,預算和時間的約束內實現和/或執行的。重要的是,當測試開始失控且不按計劃地運行時,由于預期無法實際,測試人員往往承受了來自管理層和利益相關者的巨大壓力。
因此,測試人員必須有效地計劃測試并制定正確的測試用例,選擇并執行合適的用例,監控過程,以確保有效利用工作資源和時間。所以,要列出這些無疑是一項艱巨的任務;要有效地實施,測試人員需要受過適當的教育和培訓并擁有贏得管理層支持的能力。
一般情況下,測試人員會用兩種不同的測試方法,其中,使用常規方法,測試人員主要是嘗試用所有可能的輸入去測試一個模塊或組件,用所有可能的軟件結構去實踐。盡管這種做法仍在使用,測試人員卻在慢慢灌輸推理軟件的一切的價值,最終使他們能夠檢測出所有可能存在的缺陷。但見多識廣且有學問的測試員們都明白,這在現實或經濟上是不可行,不可實現的目標。
現在,另一種方法可能就是讓測試員們隨機選擇測試輸入,希望這些測試能將大的缺陷找出來。不過,測試專家認為,隨機生成的測試輸入在評估系統的質量屬性方面表現紀錄欠佳。所以,從測試的角度來看,這是一個無休止的爭論和懸而未決的問題。盡管如此,我們還是認為,測試員的最終目標是了解測試的功能、輸入/輸出域和使用環境,等等。
同樣,對于某些特定類型的測試,測試人員也需要詳細地了解代碼是如何構造的。此外,測試人員也需要利用關于常在軟件開發或維護過程中生成的特定缺陷的知識。有了這些信息,測試者就必須明智地選擇測試輸入的子集,以及被認為最有可能找測試過程中條件和限制內的缺陷的測試輸入組合。然而,這個過程需要時間和精力。所以,測試人員知道且贊同:只有開發出基于執行的測試的有效測試用例,才能最大化和/或優化對時間和資源的利用。
“有效測試用例”我們是指:“一個很可能找出缺陷的測試用例” 。因此,制定有效測試用例的能力對于一個組織邁向一個更高質量的測試過程來說是非常重要的;反過來,一個組織邁向一個更高質量的測試過程對制定有效測試用例的能力也有許多積極影響。
例如,如果測試用例是有效的,那么:
檢測缺陷的概率更大。
更有效地利用組織資源。
測試再用的可能性更高。
更符合測試、項目進度、預算,更重要地,提供更高質量的軟件產品的可能性。
測試用例設計方法 - 概念化
上面介紹了有效測試用例的種種好處,但縝密考慮測試人員用來設計這些有效測試用例的方法也同樣重要。為了回答這個問題,有必要把軟件作為一個精心設計的產品來查看和/或檢查。現在,有了這個觀念,就有兩個基本方法可以用來設計測試用例:
黑盒(有時也稱為功能或規格)測試方法。
白盒(有時也稱為clear或透明盒 )測試方法。
使用
黑盒測試 方法,測試人員把SUT (測試中的軟件)當作一個不知道其內部結構(即如何運作)的不透明盒子,測試人員只知道它的作用。使用這種方法的SUT的大小可以是一個簡單的模塊、成員函數、對象群、一個子系統、或一個完整的軟件系統。此外, SUT的基礎行為或功能的描述可以由正式規格,輸入/處理/輸出圖( IPO),或一套定義明確的先決、后置條件來提供;重要的是,另一個值得一提的信息來源是:需求規格說明文檔,通常描述SUT的功能,輸入及預期輸出。現在,鑒于上述來源,測試員提供指定輸入到SUT,進行測試運行,然后確定所產生的輸出是否與說明文檔中提供的一致。因為黑盒測試方法只考慮了軟件的行為和功能,它通常被稱為
功能測試 ,或基于規范的測試。這種方法特別有用,極有助于找到要求和規格中的缺陷。
與此相反,
白盒測試 方法關注將被測試的軟件的內部結構。因此,使用白盒測試方法來設計測試用例,測試人員應該先了解結構,且為了實現這一目標,必須可隨時參考和理解代碼或適當的類偽代碼的要求。一旦對結構有了必要的了解,測試者就可以選擇合適的測試用例去實踐特定的內部結構要素,并確定它們是否正常工作。例如,測試用例通常被設計來實踐所有語句或發生在一個模塊或成員函數中的真/假分支。但是,由于白盒測試的設計,執行和結果分析非常耗時,這種方法被限制和/或通常只適用于軟件的小部分,如模塊或成員函數。然而,白盒測試方法對于找出設計和基于代碼的控件的邏輯缺陷和順序缺陷,初始化缺陷和數據流缺陷等特別有用。
然而,從測試員的角度來看,要實現向用戶提供低缺陷高質量的軟件的目標,必須把這兩種方法都用來設計測試用例。另外,這兩種方法都支持測試員選擇有限數量的將被用于測試的測試用例。這兩種方法可以相互補充,因為每個都或許有助于找到某些特定類型的缺陷。重要的是,有了使用這兩種方法設計出的一組測試用例,測試員找到SUT中各種不同類型缺陷的機會就增加了。
測試員還有一套有效的可再用的用來進行回歸測試(更改后的重新測試),以及
軟件測試 的新版本。
上面是一份概要:使用任一設計方法制定測試用例的各種可用方法。
但是,在使用任一設計方法準備測試用例前有一些因素需要考慮清楚。它們分別是:
測試相關風險。
預期缺陷類型。
測試員的知識和經驗。
測試水平和必須進行分組和管理的小組活動。
用于執行測試用例的工具。
應用程序,軟件和問題域的類型。
客戶要求,等等。
本人現在外包到阿里
工作 ,最近被分配的一個工作就是--路由器app測試,寫這個
文章 是為了記錄一下,方便自己查看。
剛分到阿里,各種不適應。1.路由器板子性能超級差,還沒開始測就掛了。2.分到手的電腦超級爛,打開一個頁面都要卡上好久。再加到對那邊環境的不熟悉,導致
心情 非常煩躁。幸虧那邊接口人幫我們換了好的電腦,開發們也一直加班加點,第二天來,基本功能能操作,說明基本能
測試 了。
這個路由器有兩個頻段,2.4G和5G,可以通過
web 頁面和手機app控制路由器,而我主要測的是
蘋果 手機app的
軟件測試 。由于測試過程中會有bug,我們必須提交
手機 端與路由器端的日志。手機端要抓日志,裝了一個itool,itunes。通過這個工具可以實時抓捕手機日志。還可能通過airplay,映射圖片到電腦,進行截圖。至于路由器端的日志,可以裝一個串口工具。而我因為板子串口有問題,只能裝一個xshell,遠程通過命令訪問路由器。
測試總共經歷了二周半,以下幾點,用于提醒自己以后測試中注意:
1.在正式測試前,了解所有的功能需求,以防測試過程中出現誤解。
2.如果有app與web端,兩者可以交互測試。比如web端修改密碼,手機端的反映。還有另外的一些,看會不會有影響。
3.同一個軟件,再兩個或兩個以上的手機上操作會怎么樣。
4.測一個功能A時,能不能連帶測另一個功能B。再看看會不會影響A的功能。
5.軟件重啟或恢復出廠設置,會不會影響升級。
6.文本框名稱密碼,是否支持特殊字符,中文字符,全角字符。
7.了解一些基本的接口名稱,可以通過日志知道,定位問題,知道是路由器的問題還是手機app的問題。
8.如果測了ios,就要再去測測android,因為ios比android穩定,可能你會發現更多android的問題。也有可能通過android測試發現一些android問題,交互測試也很重要。
以上是我現在能想到的一些,有新的內容,再補充。
在Linux中,僅等待CPU時間的進程稱為就緒進程,它們被放置在一個運行隊列中,一個就緒進程的狀 態標志位為TASK_RUNNING。一旦一個運行中的進程時間片用完, Linux 內核的調度器會剝奪這個進程對CPU的控制權,并且從運行隊列中選擇一個合適的進程投入運行。
當然,一個進程也可以主動釋放CPU的控制權。函數 schedule()是一個調度函數,它可以被一個進程主動調用,從而調度其它進程占用CPU。一旦這個主動放棄CPU的進程被重新調度占用 CPU,那么它將從上次停止執行的位置開始執行,也就是說它將從調用schedule()的下一行代碼處開始執行。
有時候,進程需要等待直到某個特定的事件發生,例如設備初始化完成、I/O 操作完成或定時器到時等。在這種情況下,進程則必須從運行隊列移出,加入到一個等待隊列中,這個時候進程就進入了睡眠狀態。
Linux 中的進程睡眠狀態有兩種:
一種是可中斷的睡眠狀態,其狀態標志位TASK_INTERRUPTIBLE;
另一種是不可中斷的睡眠狀態,其狀態標志位為TASK_UNINTERRUPTIBLE。可中斷的睡眠狀態的進程會睡眠直到某個條件變為真,比如說產生一個硬件中斷、釋放 進程正在等待的系統資源或是傳遞一個信號都可以是喚醒進程的條件。不可中斷睡眠狀態與可中斷睡眠狀態類似,但是它有一個例外,那就是把信號傳遞到這種睡眠 狀態的進程不能改變它的狀態,也就是說它不響應信號的喚醒。不可中斷睡眠狀態一般較少用到,但在一些特定情況下這種狀態還是很有用的,比如說:進程必須等 待,不能被中斷,直到某個特定的事件發生。
在現代的Linux操作系統中,進程一般都是用調用schedule()的方法進入睡眠狀態的,下面的代碼演示了如何讓正在運行的進程進入睡眠狀態。
sleeping_task = current;
set_current_state(TASK_INTERRUPTIBLE);
schedule();
func1();
/* Rest of the code ... */
在第一個語句中,程序存儲了一份進程結構指針sleeping_task,current 是一個宏,它指向正在執行的進程結構。set_current_state()將該進程的狀態從執行狀態TASK_RUNNING 變成睡眠狀態TASK_INTERRUPTIBLE。 如果schedule()是被一個狀態為TASK_RUNNING 的進程調度,那么schedule()將調度另外一個進程占用CPU;如果schedule()是被一個狀態為TASK_INTERRUPTIBLE 或TASK_UNINTERRUPTIBLE 的進程調度,那么還有一個附加的步驟將被執行:當前執行的進程在另外一個進程被調度之前會被從運行隊列中移出,這將導致正在運行的那個進程進入睡眠,因為它已經不在運行隊列中了。
我們可以使用下面的這個函數將剛才那個進入睡眠的進程喚醒。
wake_up_process(sleeping_task);
在調用了wake_up_process()以后,這個睡眠進程的狀態會被設置為TASK_RUNNING,而且調度器會把它加入到運行隊列中去。當然,這個進程只有在下次被調度器調度到的時候才能真正地投入運行。
2、無效喚醒
幾乎在所有的情況下,進程都會在檢查了某些條件之后,發現條件不滿足才進入睡眠。可是有的時候進程卻會在 判定條件為真后開始睡眠,如果這樣的話進程就會無限期地休眠下去,這就是所謂的無效喚醒問題。在
操作系統 中,當多個進程都企圖對共享數據進行某種處理,而 最后的結果又取決于進程運行的順序時,就會發生競爭條件,這是操作系統中一個典型的問題,無效喚醒恰恰就是由于競爭條件導致的。
設想有兩個進程A 和B,A 進程正在處理一個鏈表,它需要檢查這個鏈表是否為空,如果不空就對鏈表里面的數據進行一些操作,同時B進程也在往這個鏈表添加節點。當這個鏈表是空的時候,由于無數據可操作,這時A進程就進入睡眠,當B進程向鏈表里面添加了節點之后它就喚醒A 進程,其代碼如下:
A進程:
1 spin_lock(&list_lock);
2 if(list_empty(&list_head)) {
3 spin_unlock(&list_lock);
4 set_current_state(TASK_INTERRUPTIBLE);
5 schedule();
6 spin_lock(&list_lock);
7 }
8
9 /* Rest of the code ... */
10 spin_unlock(&list_lock);
B進程:
100 spin_lock(&list_lock);
101 list_add_tail(&list_head, new_node);
102 spin_unlock(&list_lock);
103 wake_up_process(processa_task);
這里會出現一個問題,假如當A進程執行到第3行后第4行前的時候,B進程被另外一個處理器調度投入運行。在這個時間片內,B進程執行完了它所有的指令,因此它試圖喚醒A進程,而此時的A進程還沒有進入睡眠,所以喚醒操作無效。在這之后,A 進程繼續執行,它會錯誤地認為這個時候鏈表仍然是空的,于是將自己的狀態設置為TASK_INTERRUPTIBLE然后調用schedule()進入睡眠。由于錯過了B進程喚醒,它將會無限期的睡眠下去,這就是無效喚醒問題,因為即使鏈表中有數據需要處理,A 進程也還是睡眠了。
3、避免無效喚醒
如何避免無效喚醒問題呢?我們發現無效喚醒主要發生在檢查條件之后和進程狀態被設置為睡眠狀態之前, 本來B進程的wake_up_process()提供了一次將A進程狀態置為TASK_RUNNING 的機會,可惜這個時候A進程的狀態仍然是TASK_RUNNING,所以wake_up_process()將A進程狀態從睡眠狀態轉變為運行狀態的努力 沒有起到預期的作用。要解決這個問題,必須使用一種保障機制使得判斷鏈表為空和設置進程狀態為睡眠狀態成為一個不可分割的步驟才行,也就是必須消除競爭條 件產生的根源,這樣在這之后出現的wake_up_process ()就可以起到喚醒狀態是睡眠狀態的進程的作用了。
找到了原因后,重新設計一下A進程的代碼結構,就可以避免上面例子中的無效喚醒問題了。
A進程:
1 set_current_state(TASK_INTERRUPTIBLE);
2 spin_lock(&list_lock);
3 if(list_empty(&list_head)) {
4 spin_unlock(&list_lock);
5 schedule();
6 spin_lock(&list_lock);
7 }
8 set_current_state(TASK_RUNNING);
9
10 /* Rest of the code ... */
11 spin_unlock(&list_lock);
可以看到,這段代碼在測試條件之前就將當前執行進程狀態轉設置成TASK_INTERRUPTIBLE了,并且在鏈表不為空的情況下又將自己置為TASK_RUNNING狀態。這樣一來如果B進程在A進程進程檢查了鏈表為空以后調用wake_up_process(),那么A進程的狀態就會自動由原來TASK_INTERRUPTIBLE變成TASK_RUNNING,此后即使進程又調用了schedule(),由于它現在的狀態是TASK_RUNNING,所以仍然不會被從運行隊列中移出,因而不會錯誤的進入睡眠,當然也就避免了無效喚醒問題。
4、Linux內核的例子
在Linux操作系統中,內核的穩定性至關重要,為了避免在Linux操作系統內核中出現無效喚醒問題,Linux內核在需要進程睡眠的時候應該使用類似如下的操作:
/* ‘q’是我們希望睡眠的等待隊列 */
DECLARE_WAITQUEUE(wait,current);
add_wait_queue(q, &wait);
set_current_state(TASK_INTERRUPTIBLE);
/* 或TASK_INTERRUPTIBLE */
while(!condition) /* ‘condition’ 是等待的條件*/
schedule();
set_current_state(TASK_RUNNING);
remove_wait_queue(q, &wait);
上面的操作,使得進程通過下面的一系列步驟安全地將自己加入到一個等待隊列中進行睡眠:首先調用DECLARE_WAITQUEUE ()創建一個等待隊列的項,然后調用add_wait_queue()把自己加入到等待隊列中,并且將進程的狀態設置為 TASK_INTERRUPTIBLE 或者TASK_INTERRUPTIBLE。然后循環檢查條件是否為真:如果是的話就沒有必要睡眠,如果條件不為真,就調用schedule()。當進程 檢查的條件滿足后,進程又將自己設置為TASK_RUNNING 并調用remove_wait_queue()將自己移出等待隊列。
從上面可以看到,Linux的內核代碼維護者也是在進程檢查條件之前就設置進程的狀態為睡眠狀態,
然后才循環檢查條件。如果在進程開始睡眠之前條件就已經達成了,那么循環會退出并用set_current_state()將自己的狀態設置為就緒,這樣同樣保證了進程不會存在錯誤的進入睡眠的傾向,當然也就不會導致出現無效喚醒問題。
下面讓我們用linux 內核中的實例來看看Linux 內核是如何避免無效睡眠的,這段代碼出自Linux2.6的內核(linux-2.6.11/kernel/sched.c: 4254):
4253 /* Wait for kthread_stop */
4254 set_current_state(TASK_INTERRUPTIBLE);
4255 while (!kthread_should_stop()) {
4256 schedule();
4257 set_current_state(TASK_INTERRUPTIBLE);
4258 }
4259 __set_current_state(TASK_RUNNING);
4260 return 0;
上面的這些代碼屬于遷移服務線程migration_thread,這個線程不斷地檢查kthread_should_stop(),直到kthread_should_stop()返回1它才可以退出循環,也就是說只要kthread_should_stop()返回0該進程就會一直睡 眠。從代碼中我們可以看出,檢查kthread_should_stop()確實是在進程的狀態被置為TASK_INTERRUPTIBLE后才開始執行的。因此,如果在條件檢查之后但是在schedule()之前有其他進程試圖喚醒它,那么該進程的喚醒操作不會失效。
小結
通過上面的討論,可以發現在Linux 中避免進程的無效喚醒的關鍵是在進程檢查條件之前就將進程的狀態置為TASK_INTERRUPTIBLE或TASK_UNINTERRUPTIBLE,并且如果檢查的條件滿足的話就應該將其狀態重新設置為TASK_RUNNING。這樣無論進程等待的條件是否滿足, 進程都不會因為被移出就緒隊列而錯誤地進入睡眠狀態,從而避免了無效喚醒問題。
因為我這里有兩臺機子,我打算這樣演示:
一臺機子啟動一個作為主點節的hub 和 一個作為次節點的hub(系統windows 瀏覽器為ie) ip為:192.168.40.24
另一臺機子啟動兩個次節點hub,一個次節點瀏覽器為firefox,另一個瀏覽器為chrome (系統為windows),ip為:192.168.40.67
啟動各節點hub
啟動主節點hub命令:
java -jar selenium-server-standalone-2.24.1.jar -role hub
啟動與主節點同一機子的次節點hub命令:
java -jar selenium-server-standalone-2.24.1.jar -role node -hub http://localhost:4444/grid/register -browser browserName="internet explorer"
啟動另外一臺機子的兩個節點hub命令分別為:
啟動firefox的
java -jar selenium-server-standalone-2.24.1.jar -Dwebdriver.firefox.bin="D:/Program Files/Mozilla Firefox/firefox.exe" -role webdriver -hub http://192.168.40.24:4444/grid/register -browser browserName=firefox
其中-Dwebdriver.firefox.bin="D:/Program Files/Mozilla Firefox/firefox.exe"這個是傳我的firefox瀏覽器安裝地址,不然找不到。
啟動chrome的
java -jar selenium-server-standalone-2.24.1.jar -Dwebdriver.chrome.driver="D:/chromedriver.exe" -role webdriver -hub http://192.168.40.24:4444/grid/register -port 6666 -browser browserName=chrome
其中-Dwebdriver.chrome.driver="D:/chromedriver.exe",這個是傳入我chromedriver.exe的放置地址。端口設為6666,防止和上面firefox的重復。
鏈接好后,可以在http://localhost:4444/grid/console可以查看到三個子節點的狀態。啟動詳細方法可以參考前面的
文章 。
Selenium Grid只是提供多系統、多瀏覽器的執行環境,而不是說任務一個test case丟給它就能并行運行。并行的運行我這里就交給testng了。看下面代碼和配制。
testcase 代碼 和 testng.xml
testcase代碼:
package driver;
import java.net.MalformedURLException;
import java.net.URL;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class GridParallelTests {
private WebDriver dr;
DesiredCapabilities test;
String baseUrl;
@Parameters({"browser","nodeUrl","webSite"})
@BeforeMethod
public void setUp(String browser,String nodeUrl,String webSite){
baseUrl = webSite;
if(browser.equals("ie")) test = DesiredCapabilities.internetExplorer();
else if(browser.equals("ff")) test = DesiredCapabilities.firefox();
else if(browser.equals("chrome")) test = DesiredCapabilities.chrome();
else System.out.println("browser參數有誤,只能為ie、 ff、chrome");
String url = nodeUrl + "/wd/hub";
URL urlInstance = null;
try {
urlInstance = new URL(url);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("實例化url出錯,檢查一下url格式是否正確,格式為:http://192.168.40.67:5555");
}
dr = new RemoteWebDriver(urlInstance,test);
dr.get(webSite);
}
@Test
public void test(){
dr.get(baseUrl);
dr.findElement(By.id("kw")).sendKeys("selenium");
dr.findElement(By.id("su")).click();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("title:"+dr.getTitle());
}
@AfterMethod
public void quit(){
dr.close();
}
}
testng.xml:
<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
<suite name="Suite1" parallel="tests" thread-count="5">
<test name="test1">
<parameter name="browser" value="ff"/>
<parameter name="nodeUrl" value="http://192.168.40.67:5555"/>
<parameter name="webSite" value="http://www.baidu.com"/>
<classes>
<class name="driver.GridParallelTests"></class>
</classes>
</test>
<test name="test2">
<parameter name="browser" value="chrome"/>
<parameter name="nodeUrl" value="http://192.168.40.67:6666"/>
<parameter name="webSite" value="http://www.baidu.com"/>
<classes>
<class name="driver.GridParallelTests"></class>
</classes>
</test>
<test name="test3">
<parameter name="browser" value="ie"/>
<parameter name="nodeUrl" value="http://192.168.40.24:5555"/>
<parameter name="webSite" value="http://www.baidu.com"/>
<classes>
<class name="driver.GridParallelTests"></class>
</classes>
</test>
</suite>
運行testng.xml就可以了。
如果你是用ant把上面的參數傳進去也是可以的。我這里就直接簡單地放在testng.xml了。
1.啟動Samples-Web-Start
Web Server 時,提示Could not open port 1080-Port is already used by another server(wsaeaddrinuse)
解決方法:
找到xitami.cgf,將protbase=1000改為2000
[C:\Program Files\HP\LoadRunner\WebTours]
2.啟動Samples-Web-Start Web Server時,提示your request was unsuccessful,Cannot create CGI process
解決方法:
a.可能未安裝strawberry-perl.
b.如正常安裝,請打開WebTours文件夾下的run.bat,查看其SET PATH路徑設置是否正確,尤其是perl安裝路徑,此BAT后默認perl安裝在C盤,c:\strawberry\c\bin;c:\strawberry\perl\bin 如你安裝strawberry并非此路路徑,在此修改BAT保存是沒用的,需重新安裝perl到C盤,或COPY一份到C盤下。重啟start web server.服務.
3.LoadRunner Sample WebTours 點擊Flights出現空白解決方法
解決方法:找環境變量,發現PERL5LIB變量中的值與LOG文件的匹配,值為:D:\oracle\product\10.2.0\db_2\perl\5.8.3\lib\MSWin32-x86;D:\oracle\product\10.2.0\db_2\perl\5.8.3\lib;D:\oracle\product\10.2.0\db_2\perl\5.8.3\lib\MSWin32-x86;D:\oracle\product\10.2.0\db_2\perl\site\5.8.3;D:\oracle\product\10.2.0\db_2\perl\site\5.8.3\lib;D:\oracle\product\10.2.0\db_2\sysman\admin\scripts;
去除所有帶5.8.3的值,修改后的值為D:\oracle\product\10.2.0\db_2\sysman\admin\scripts;
此時sample運行正常。但不知道對ORACLE有什么影響。
怕對oracle有影響,我在StartServer.bat里加上了對這個變量的設置
編輯StartServer.bat 在最上面加上SET PERL5LIB=C:\oracle\product\10.2.0\db_1\sysman\admin\scripts