在軟件工程中,非功能性需求(nonfunctional requirements,簡稱NFRs)與軟件架構(software architectures,簡稱SAs)之間存在著緊密聯系。早在1994年,Rick Kazman和Len Bass就肯定地說過,軟件架構與實現非功能性需求之間存在密切聯系。這一想法在
軟件開發領域已經流行很多年,它也解釋了為什么開發項目要在實現非功能性需求方面做大量投入。
當我們認識到軟件架構的概念如何從簡單的結構性表示演變為決策視角時,這個籠統的觀點就顯得更加具體了。 從決策角度來看,非功能性需求是對各種設計方案進行選擇的標準。4 例如,從可維護性或可移植性方面考量,需要一種層次性架構風格;從效率方面考量,需要一種專門的
數據庫技術。
軟件架構師在執行軟件架構設計任務時,必須連續不斷地應對非功能性需求。他們必須了解系統有哪些非功能性需求,以及架構決策對實現這些非功能性需求的影響。 在本文中,我們將介紹一項實證研究,它揭示了軟件架構師們在決策過程中應對非功能性需求的有關實踐。這項研究以一個調研活動為基礎,該調研活動由兩部分組 成。首先,我們從工程角度對非功能性需求加以分析,尤其是與三類需求工程活動(獲取、文檔化和驗證)的關系。然后,我們深入研究了非功能性需求是如何影響 架構決策的。
調研
我們針對同一個軟件項目,多次組織了半結構化訪談(semi-structured interviews),訪談的對象都是參與過該項目的軟件架構師。相對其他定性研究策略(如結構化問卷調查)而言,半結構化訪談更具靈活性,它使我們可 以更好地研究對話中出現的相關問題。另外,我們把討論范圍限定在單個軟件項目以內,而不是考慮一般性的架構原則,這有助于我們更好地理解與評估背景信息。
訪談對象及所在機構
本調研涉及13位訪談對象,他們來自12家跨越不同業務與應用領域的軟件密集型機構(見表1)。根據業務種類不同,這些機構可分為三類:
軟件咨詢公司,主要是為客戶從事軟件開發任務。
IT部門,為滿足機構內部需求而從事或外包軟件開發任務。
軟件供應商,開發特定私有方案,并將其商品化。
本調研涉及的軟件項目,其功能與大小也有差別。
盡管所有訪談對象都在各自項目中履行架構師職責,但他們的所在機構并沒有專門設置軟件架構師職位。相反,機構是根據技術知識或經驗來為各個項目選擇架構師的。除去一個例外,其他所有訪談對象都同時還兼任其他角色(如項目經理、顧問或開發者)。
訪談實施
我 們為訪談制作了一個訪談指南,并通過兩位研究者和兩位軟件架構師對它進行了
測試,以確保有效。然后,我們把訪談指南預先發送給所有訪談對象,讓他們有機會 熟悉訪談話題,并挑選一個用于訪談的項目。訪談是面對面進行的,每次訪談大約一小時。我們對訪談進行了錄音,然后將它們轉錄為文本,以便進行分析。而后, 我們請訪談對象來驗證轉錄內容。有時,我們會明確請求訪談對象澄清某些方面。我們使用了NVivo軟件來評估收集到的數據。我們對所有語句和詞語進行了歸類,把描述相同想法、動作或屬性的語句和詞語歸為一組。最后,我們根據機構和項目的特征來分析了數據。
局限性
我們了解我們的樣本不是隨機的,因此未必能夠代表更廣泛的軟件開發全體。所以,為了試圖緩解可能存在的偏差,我們讓機構自己挑選訪談對象,并允許訪談對象自 己挑選項目。我們承認,訪談對象可能會傾向于選擇較為成功的項目。為了緩和這一問題,我們向訪談對象說明,該項研究不用于分析最佳實踐,只是想了解做事方 式。我們承諾為反饋內容保密。大部分機構是中小型機構,而且都來自西班牙。當然,調研結果可能受到上述因素的影響。此外,大部分都不是緊要領域的項目。不 過,由于我們試圖通過這些項目來揭示工業界實踐,而不是提出一般性理論,所以這不算重大弱點。
架構師如何應對非功能性需求
我們向軟件架構師們提出了好幾個具體的問題,關于他們如何獲取并文檔化非功能性需求,以及之后如何在系統中進行驗證。我們認為,這對理解架構師在項目中進行決策制定的背景十分重要。關于這部分的詳情,請參見我們的另一篇文章6。問題列表見下。由于我們實施的是半結構化訪談,因此這些問題只是作為指導,訪談是依據對話情況來推動的。關于需求獲取、文檔化和驗證方面的話題自然而然地在對話中出現。
獲取非功能性需求,由誰負責?
需求獲取的目的是從涉眾等處得到系統需求,并細化之。研究者和實踐者都認同需求獲取是需求工程中最具挑戰的部分。致力于精確無歧義表達需求的技術有很多,如調研、創意研討會等。
這些技術假定來自客戶方面的涉眾(最終用戶、經理等)在需求獲取方面將貢獻很多。就功能性需求而言,一些訪談對象認同該假定。例如,訪談對象A說:“[業務分析師]編寫一個詳細的文檔來反映所有[功能性]需求”。?
但是,該假定對非功能性需求來說并不成立。在我們的調研中,有10個項目,軟件架構師是非功能性需求的主要來源。有些客戶從未提到非功能性需求。訪談對象E 說:“[客戶]從沒提到過網頁加載時間不能超過2秒這樣的需求,但他后來卻對此頗有抱怨。”訪談對象L2說:“客戶提到一個基本的[非功能性需求],然后 我們根據自己的經驗作了補充”。”
這一數值已經超過了Uwe van Heesch和Paris Avgeriou提到的架構師顯著涉及需求獲取的比例(60%)。7
只有訪談對象D、H、I的所在機構是由客戶來領導非功能性需求獲取的。有趣的是,也只有這幾個機構的項目是外包的(管理方分別是一家航空工業公司、一家軟件 公司和一家銀行)。這一情況是由機構之間的從屬關系造成的。然而,即便在這些案例中,架構師仍然在定義非功能性需求方面發揮著積極作用。訪談對象D說: “我們的客戶是一個航空系統部門,所以所有非功能性需求都是良好定義的。另外,我們需要基于我們的經驗再補充一些非功能性需求。?”
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
如何獲取非功能性需求?
非功能性需求難以捉摸的特性,決定了不容易事先獲取。根據這條一般性的看法,所有訪談對象都認同非功能性需求的獲取是一個迭代的過程,需要跨越整個系統生命 周期。因為在達到一定重要階段(通常是原型)之前,可能不太容易對系統的部分行為提出期望。訪談對象J稱:“我們首先確定一些相關的非功能性需求,比如與 其他系統的兼容性等,然后開發一個原型,并分析其他候選方案。”?
此外,我們無法在第一次開發之前把非功能性需求考慮完全。他們需要糾正性維護, 以糾正未符合預期的不正確行為。訪談對象K說,“在效率方面,我們必須作出改變,因為在項目開始之時并沒有就服務水平提出要求。”?這樣是合理的。有些非 功能性需求(例如安全性方面)只有在目標環境中部署系統或意外發生時,才能進行全面檢查。
如何檔案化非功能性需求?
為了讓檔案化更加有效,學術界與標準化組織已經提出了許多用于編寫系統需求規格說明書的表示法和模版。然而,13位訪談對象中有9位承認他們不對非功能性需 求進行檔案化。訪談對象H說:“[功能性需求]是用UML、概念模型、用例來表示的,但沒聽說過非功能性需求。”一些訪談對象說,只有當客戶需要,或者項 目屬于緊要領域時,才有必要檔案化。有四位訪談對象表示他們明確記錄非功能性需求。訪談對象D的所在機構采用一種領域特定語言(domain- specific language)。“因為我們為航空領域工作,我們必須以可驗證的方式來明確表達非功能性需求。我們有專門的模版,我們采用來自其他工程領域的不同技術 (如風險模型、故障樹等)。”兩位訪談對象表示,他們采用具有一定結構的自然語言來記錄非功能性需求。訪談對象B采用Volere需求模版(它提供了一個 高度結構化的需求模版);訪談對象K采用符合ISO/IEC 9126質量模型的純文本。
訪談對象J只采用純文本文檔。只有訪談對象B和 D是不斷維護需求文檔的;J和K只記錄最初的非功能性需求。訪談對象K說:“起初,我們用自然語言記下一些關于非功能性需求的想法,... 不過之后,我們并沒有跟蹤它們,在設計過程中也沒有出現新的非功能性需求。”人們似乎很自然地認為,可度量性與連續(或至少規律的)記錄更新之間存在一定 關系。但要確認這種關系是否存在,需要做進一步研究。
所以我們可以看到,非功能性需求很多是不言而喻的,甚至是隱含的。把它們檔案化,準 確性和及時性會受到嚴重損害。這種情況可以用成本和收益來解釋。訪談對象C直率地說:“我幾乎不對項目進行適當的檔案化,主要是它耗費太多錢。”如果實踐 者們無法從中感到益處,那么非功能性需求將繼續保持難以捉摸的狀態。
如何在系統中驗證非功能性需求?
驗證系統的行為 是否滿足非功能性需求是有難度的。不同非功能性需求之間存在差異,因此相應的驗證方法也有所不同。不過,有11位訪談對象說,所有非功能性需求都在項目中 得到了滿足,盡管總有改進余地。然而,當我們問道如何針對非功能性需求進行驗證時,他們的回答顯得含糊。訪談對象D是這么說的:“對于一些[不是全部]非功能性需求,由于不容易測試,我們只是非正式地跟客戶進行了討論。“因此,我們有必要把自以為滿足非功能性需求(正如訪談對象中的那11位(85%)所做 的)和真正的驗證區分開來(訪談對象中有8位(61%)對某些類型的非功能性需求進行了驗證)。(這與過去研究得出的60%是相稱的。8)
八位訪談對象執行了一些非功能性需求的驗證,不過僅限于一到三種。他們只考慮以下類型的非功能性需求。
性能效率。訪談對象H說:“我們通過負載和壓力測試來進行性能評估。”?
正確性。訪談對象A說:“我們每編碼一小時,就投入一小時來測試。”?
易用性。訪談對象K說:“我們制作了一個原型,確保客戶對用戶界面滿意。”?
可靠性。訪談對象J說:“我們強行引入一些錯誤,看看系統會發生什么,會不會丟失數據等。”?
安全性,作為十分重要的一類非功能性需求,所有訪談對象都沒有提到。訪談對象F描述了一個極端的不作驗證的例子:“我們等客戶來抱怨,他們會發現問題的。” 盡管這是個不令人滿意的回復,但它再次反映了這點(和前面提到的檔案化一樣):出于預算和時間上考慮,工程實踐可能沒法按照理想的方式進行。
與之形成鮮明對比的是,訪談對象D采用基于統計分析和模擬的形式化方法來檢查系統的可靠性。當然,這是預料之中的,因為他們的項目涉及到航天工業中的信息系統,屬于緊要領域。過去有研究發現,評估方法與評估目標有關。9 我們的發現與之不謀而合。
我們有一個可能與前人研究結果一致的發現,即檔案化與驗證之間的聯系。如Andreas Borg及其同事所說的那樣,“如果用不可度量的詞語來表達需求,那么測試會很消耗時間,甚至根本無法測試。”10僅有兩位訪談對象采用了可度量的方式來表達非功能性需求,這可能是驗證水平整體較低的原因之一。
非功能性需求如何影響架構決策
毫無意外,所有訪談對象都認同:非功能性需求會影響他們的決策。但是他們的具體回答反映出了一些細微差別。
決策類型
非功能性需求影響著四類決策。
架構模式
對于給定類型的項目,大部分訪談對象會很自然地選擇層次架構,盡管他們中有些人明確給出了決策理由。訪談對象J說:“我們采用層次架構,因為它允許以后變化。”?
實現策略
有些類型的需求可能需要具體的架構級策略。它可以是一般性的設計決策(比如訪談對象L1說“我們采用單點登錄,以增強子系統的集成性”),也可以是有關個別組件的具體決策(比如訪談對象A說“我們為數據庫表建立副本,因為訪問時間過長”)。?
橫向決策
有 些非功能性需求會影響到整體架構。訪談對象L1說,“我們更傾向于采用我們已經掌握的技術。”一個反復出現的問題是,第三方組件尤其是開源軟件(open source software,OSS)的使用。訪談對象D說,“出于可維護性考慮,我們希望能夠獲得源代碼,所以我們選擇了開源軟件方案。”?
技術平臺
非功能性需求也許可以通過選擇正確的數據庫或中間件等來滿足。在這種情況下,它們可能是影響整個系統的。訪談對象K說:“我們需要高可用性 (availability),而只有Oracle能夠保證這一需求。”非功能性需求也可能是局部的。訪談對象H說:“有一個查詢是直接通過 JDBC(Joint Database Connectivity)實現的,由于效率原因,所以沒有采用Hibernate。”?
不同的決策制定過程
我 們在本次調研中發現了一個關于決策制定的特別方面,即技術決策與其他決策的交織。我們聽到三種不同的反饋。有四位訪談對象表示,非技術性決策優先。訪談對 象C說:“架構師應該在之前設計好的邏輯結構上,選用合適的技術。”另外四位訪談對象說,重大技術決策優先,之后的決策應該與之配合。訪談對象H說:“客 戶給我們設了一些限制,比如,架構必須基于開源軟件(OSS)和Java。”而其他五位訪談對象認為,技術決策和其他決策是交叉并彼此影響的,可以看成是 一種架構設計層面上的局部雙峰模型。11
影響程度
我們詢問訪談對象在進行架構決策時會考慮哪些非功能性需求。我們以ISO/IEC 25000質量標準為統一框架,將他們的回答匯總如下。
明確性(Explicitness)
很明顯,架構師們期望一定的非功能性需求,即便還沒有將它們作為需求明確列出。訪談對象I說:“我不會考慮一個不安全的系統。”由于所采用技術與平臺的當前 特性,這些不言而喻的非功能性需求經常浮現在架構師的腦海里。訪談對象E說:“我們不會去考慮文檔的安全性,因為它是由SharePoint管理系統負責 的。”?
來源(Source)
有些需求直接來自開發團隊或架構師。訪談對象B說:“未來要維護這個系統的人是我們, 所以,確保它的可維護性對我們來說是很重要的。”相對于來自客戶的非功能性需求,這些來自開發團隊的非功能性需求與架構決策過程更加接近,因為技術人員從 解決方案的角度去思考,而客戶的思考角度是面向問題的。
非技術性(Nontechnicality)
非技術性的非功 能性需求(NFRs)指那些不與軟件內在質量直接相關、而是與系統環境有關的的需求,比如許可證或成本等。12架構師要考慮這些基本因素;訪談對象們表 示,所有非功能性需求中有大約40%屬于非技術性的。有時,他們會以最高優先級來考慮這些需求。訪談對象J稱:“成本是第一位的,所有別的都得服從 它。”?
重要性(Importance)
我們詢問訪談對象哪種類型的非功能性需求是最為重要的。許可證問題、易用 性、可靠性、性能效率,以及可維護性是被提到最多的。而只有兩位訪談對象提到了可移植性。我們將該信息與訪談對象在面談中提到的決策案例進行了交叉檢查; 我們發現,性能效率和可維護性對決策的影響最大。
術語問題(Terminology issues)
在與訪談對象討 論非功能性需求時,我們碰到一些術語上的問題。有些訪談對象請求對術語進行補充解釋,比如“可用性(availability)”和“準確性 (accuracy)”。其他的訪談對象會在給定上下文中錯誤地使用術語,比如用“人體工學”來表達“易用性”。有些訪談對象甚至采用錯誤的定義,比如 “可維護性(maintainability)是十分重要的,因為我們不能對運轉中的系統進行修改。”另一個常見的問題是混淆使用“性能 (performance)”與“效率(efficiency)”。ISO/IEC 25000將性能效率定義為“一定條件下相對于所用資源數量的性能”。?”13 該定義有助于我們解除混淆。
為了檢查研究中的觀察結果是否有效,我們與一些大型IT企業展開了一項新的研究。我們期望在文檔化和驗證上看到改善,并且有可能的話,在各種非功能性需求的重 視程度上有所變化。我們還想研究,如果把非功能性需求與架構決策之間的關系明確表達出來(比如,考慮了哪些權衡,放棄了哪些選擇等等)的話,將對最終的系 統架構決策有何影響。關于本課題的相關研究,請見下方。
致謝
我們非常感謝參加本課題的參與者,感謝他們的時間和貢獻。本課題獲得西班牙項目TIN2010-19130-C02-01的資助。
本文由《IEEE Software》雜志首發,現在由InfoQ和IEEE Computer Society聯合向您呈現。
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
Selenium2library在我們實際測試
web頁面的時候基本上已經夠用了,不過還是會有部分情況下會脫離Selenium2library的控制,無法進行操作。比如說下載文件的時候,要選擇保存文件在什么地方,比如說上傳文件的時候,要選擇上傳哪個文件,這些在Selenium2library下都沒有很好的處理辦法。但是結合上AutoItLibrary,就可以很好的來進行處理了。結合AutoItLibrary的內容分2篇,本篇介紹AutoItLibrary安裝使用和對話框處理,下篇介紹上傳下載。
下載解壓縮后直接用ride打開里面的tests看代碼或者運行案例即可。
1、AutoItLibrary安裝
簡單說下安裝,把下面2個下載了,先安裝pywin32,然后再安裝AutoItLibrary,解壓縮進入相應目錄執行
python setup.py install
pywin32-217.win32-py2.7.exe(我之前下載的217,最新的好像是218,版本較多,請注意py版本)
AutoItLibrary-1.1.tar.gz(必須先安裝上面的pywin32,并且Python的安裝目錄不能有空格,如果有空格會導致注冊autoit的dll時出錯。版本一直是1.1)
64位的機器:除了安裝上面2個之外,還不得不再安裝一個AutoItV3。一般情況下裝完這個就能用了。
2、AutoItLibrary對象識別
當成功安裝AutoItLibrary之后,在你的硬盤某個盤根目錄會多一個Robotframework的目錄,具體哪個盤取決于你的User目錄在哪個盤,例如我的是在D盤,因此多出來的這個目錄就在如下路徑:
D:\RobotFramework\Extensions\AutoItLibrary
這里是一些輔助工具,比如AutoItX.chm是幫助文檔,AutoItLibrary.html是
測試庫的關鍵字文檔說明,Au3Info.exe是最重要的識別對象的工具了。
在Finder Tool的位置有個十字星,可以用鼠標拖動他到你需要識別的對象上,就像下圖這樣:
AutoItLibrary的對象操作大體上有幾大主要部分,Window操作、Control操作、Mouse操作、Process操作、Run操作、Reg操作還有一些其他的操作。
其中前三個操作我比較常用,Window和Control應該比較好理解吧,你看到的窗口就是Window,窗口上的按鈕、文本框等就是Control。所以在通常要去操作Control時,一般需要先激活窗口,再操作控件。
AutoItLibrary的鼠標操作要用到真實坐標,這和Selenium2Library里的坐標略有差異,下篇會有例子。
回到上圖,可以看到最重要識別出來的屬性,分兩塊,在左側上半部分,Basic Window Info和Basic Control Info。
經過我多次的使用,Window方面識別用Title比較多,Control主要用controlID,controlID就是在Basic Control Info里的Class+Instance,比如說圖中這個對象,他的controlID就是Edit1,關鍵字里的strControl就是controlID(chm里都是寫的controlID)。
AutoItLibrary的關鍵字我就不一一介紹了,大家可以看Chm幫助或者html的關鍵字文檔,不過chm是原生AutoIt的文檔,對于理解關鍵字的作用比較有幫助。關鍵字文檔只是列出來所有的關鍵字和參數,基本很少有說明。
3、web對話框
a、你肯定見過這種對話框,前一個是只有確定的,還有確定取消2個按鈕的。
b、你應該也見過這種對話框
c、還有那種在網頁上彈出的要輸入用戶密碼的登錄框,我這里沒有找到例子,也木有截圖。(找到截圖,見最底下)
以上這些都可以用AutoItLibrary來處理。
對于a來說,Selenium2Library中的confirm action就可以處理了。
對于b、c來說,都要用AutoItLibrary處理更好一些,因為那些文本框的輸入已經脫離了Selenium2Library的控制了。
先來看a這種對話框在Selenium2Library的處理,腳本如下:
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
1、真機調試打開USB調試模式
2、啟動腳本提示apk包Could not make a string,是釋放string.json出錯,由于apk損壞導致,驗證是安裝到真機上開啟APP
3、Activity要寫對,否則提示不存在Activity,建議寫完整名稱,完整包名類似com.xxx.xxx.Activity;啟動Activity要寫對,否則提示XXX never XXX。包名參數與Activity參數可以在AndroidManifest.xml(獲取方法http://code.google.com/p/android-apktool/)中查看,包名:<manifest
android:versionCode="12" android:versionName="2.6.0.0.0" package="com.xxx.xxx",一般位于XML定義的下一行,啟動Activity在這里看,帶有LAUNCHER關鍵字<activity android:theme="@*android:style/Theme.NoTitleBar" android:label="@string/app_name"
android:name="com.xxx.xxx.SplashActivity" android:launchMode="singleTop" android:screenOrientation="portrait" ,本例中是com.xxx.xxx.SplashActivity
4、
Appium支持一個Webdriver元素定位方法的子集
find by "tag name" (i.e., 通過UI的控件類型)
find by "name" (i.e., 通過元素的文本, 標簽, 或者開發同學添加的id標示, 比如accessibilityIdentifier)
find by "xpath" (i.e., 具有一定約束的路徑抽象標示, 基于XPath方式)
5、Appium 在 Mac OS X 上安裝使用文檔,參考:http://testerhome.com/topics/166,
Windows平臺,參考:http://testerhome.com/topics/155,
Linux平臺,參考:http://testerhome.com/topics/160,Android平臺,參考:http://testerhome.com/topics/153
6、iOS模擬器—>硬件—>設備—>iPhone
7、【坑】Appium在MacOS10.9以及iOS7上面的問題:啟動appium腳本沒有問題。安裝好應用之后log中會報出500,同時instruments會顯示simulator session timeout。
8、生成build/Test.appa的方法,進入到目錄下面編譯
xcodebuild -sdk iphonesimulator6.0
9、安裝路徑問題
全局路徑,也就是帶上參數 -g 的安裝模式。這個命令會把模塊安裝在 $PREFIX/lib/node_modules 下,可通過命令 npm root -g 查看全局模塊的安裝目錄。 package.json 里定義的bin會安裝到 $PREFIX/bin 目錄下,如果模塊帶有 man page 會安裝到 $PREFIX/share/man 目錄下。
本地路徑,不帶 -g 參數的。從當前目錄一直查找到根目錄/下有沒有 node_modules 目錄,有模塊安裝到這個目錄下的 node_modules 目錄里,如果沒有找到則把模塊安裝到當前目錄 node_modules 目錄下。package.josn 定義的 bin 會安裝到 node_modules/.bin 目錄下,man page 則不會安裝。
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
1、如果需要加入一個一個的類
public static void main(String args[]){ tng.SetTestClasses(new Class[]{MyTest.class}) //這里可以加多個類。 tng.run(); } |
public static void main(String args[]){ TestNG tng = new TestNG(); RetryTestListener rtl = new RetryTestListener(); XmlSuite xs = new XmlSuite(); Parser parser = new Parser("./testxml/temp.xml"); List<XmlSuite> suites = new ArrayList<XmlSuite>(); try { suites = parser.parseToList(); } catch (ParserConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }; tng.setXmlSuites(suites); tng.addListener(rtl); tng.run(); } |
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
一、什么是同步點
同步點是指在一個
測試過程中,指示QuickTest等待應用程序中某個特定過程運行完成以后再運行下一步操作。
Waits until the specified object property achieves the specified value or exceeds the specified timeout before continuing to the next step.
測試過程中,如果需要指定QuickTest暫停運行一個測試或組件,直到特定的對象屬性存在后才開始運行下一步,那么可以插入同步點來實現。例如以下幾種情況:
判斷進度條是否已經100%完成。
判斷某一狀態消息的出現。
等待某按鈕狀態變為可用。
一個操作后,彈出一個消息對話框。
等待窗口打開并提交數據。
二、同步點方法
默認等待時間
Sync方法;
Wait方法;
WaitProperty方法;
Exist方法;
2.1 默認等待時間
1)File>>>Settings>>>Run>>>Object synchronization timeout:QTP默認對象識別同步時間為20S,可以手工更改。
2)File>>>Settings>>>Web>>>Browser navigation timeout:Web插件對于Web瀏覽器對象的默認同步時間為60s,可以手工更改。
2.2 Sync
Syntax
object.Sync
Example
Browser("Mercury Tours").Sync '等待IE加載完成
Browser("Mercury Tours").Page("Mercury Tours").Sync '等待頁面加載完成
Description
Sync方法等待瀏覽器或頁面加載完成后才進行下一步操作,Sync方法只能在WEB中使用,操作對象只有Browser(瀏覽器對象)和Page(頁面對象)。
注意:雖然Sync方法會使
QTP等待到頁面加載完成后,但無法判斷頁面是否加載成功,如果需要判斷頁面加載是否成功,可以通過判斷頁面中對象visible的屬性值。
Browser("
Google").Page("Google").WebEdit("q").GetROProperty("visible")=true
2.3 Wait方法
Syntax
object.WaitProperty (PropertyName, PropertyValue, [TimeOut])
Example
Wait 10 或Wait(10)
Description
wait方法可設定指定的等待時間,時間單位為秒,但這個時間只能是固定的,即必須等到這個時間才能繼續執行。
注意:死等待有時候會浪費時間,有時候會因設定時間過短導致找不到對象。
2.4 WaitProperty
Syntax
object.WaitProperty (PropertyName, PropertyValue, [TimeOut])
Example
windows("XXX").dialog("XXXXXXXX").waitProperty "visible",true,50000
Description
WaitProperty方法是指當指定的屬性出現后或是指定時間后指定的屬性還未出現,再進行下一步操作。
方法中的visible是屬性,true是屬性的值,50000為最長等待時間,單位為毫秒。即在最長等待時間內任意時刻visible的值為true了,腳本繼續向下執行,否則直到等到最大等待時間,然后給出waring。
注意:
1)如果超出最大等待時間,QTP報告中的結果是warning,而不是fail。
2)該方法適用于除WinMenu對象(菜單對象)以外的所有標準Windows對象
2.5 Exist
Syntax
object.Exist([TimeOut])
Example
windows("XXX").dialog("XXXXXXXX").Exist(10)
Description
方法中的10的時間單位為秒。該方法與waitproperty方法類似,當程序執行到該語句時會去檢查對象是否存在,若存在返回true,進入下一步;若10s內檢查對象一直不存在返回flase,一般用于if語言中比較多。
如果設置超時時間為0,如object.Exist 0,那么QTP不會等待,而是直接返回查找的結果(True或False)。
如果未設置超時時間,如object.Exist,那么超時時間為QTP默認的同步時間
學習心得:學習中遇到問題,不要急著四處詢問,嘗試使用自帶的操作手冊,往往有意外的收獲,看看下面
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
1. 在app/etc/local.xml 中,添加新的
數據庫選項
<?xml version="1.0"?> <config> <global> <install> <date><![CDATA[Tue, 05 Jul 2011 03:23:52 +0000]]></date> </install> <crypt> <key><![CDATA[80eb4be66ce28df745f27c75f2604d33]]></key> </crypt> <disable_local_modules>false</disable_local_modules> <resources> <db> <table_prefix><![CDATA[]]></table_prefix> </db> <default_setup> <connection> <host><![CDATA[localhost]]></host> <username><![CDATA[root]]></username> <password><![CDATA[]]></password> <dbname><![CDATA[hello]]></dbname> <active>1</active> </connection> </default_setup> <vip_space_read> <connection> <host><![CDATA[localhost]]></host> <username><![CDATA[root]]></username> <password><![CDATA[]]></password> <dbname><![CDATA[hello_dev_test]]></dbname> <model>mysql4</model> <initStatements>SET NAMES utf8</initStatements> <type>pdo_mysql</type> <active>1</active> </connection> </vip_space_read> </resources> <session_save><![CDATA[files]]></session_save> </global> <admin> <routers> <adminhtml> <args> <frontName><![CDATA[hello_admin]]></frontName> </args> </adminhtml> </routers> </admin> </config> |
2. 在需要使用的不同數據庫的model resource中,重寫 _setResource 方法,例如
class Hello_Vip_Model_Entity_Vip_Adapter extends Mage_Core_Model_Mysql4_Abstract { protected $_logFile = 'vip.adapter.log'; protected function _construct() { $this->_setResource(array('read' =>'vip_space_read', 'write' =>'vip_space_read')); } |
經過以上兩步,就能在某個model中使用不同的數據庫
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
我把之前的一些學習經驗和方法跟大家分享下,希望對大家有所幫助: 一、玩好
Linux一定要經常折騰,說白了,就是動手能力一定要強。我初學Linux那塊,家里3臺電腦,我在上面經常反反復復的做kickstart、網絡ghost、雙系統安裝的實驗。有很長一段時間,我還在其中的一臺老式筆記本上安裝了Ubuntu系統,通過它來游覽網頁和看視頻,解決各種驅動問題,通過這些折騰,對Linux也是越來越有興趣,學習的勁頭也越來越足了。
二、床邊經常放幾本書,臨睡覺前或無聊時經常翻一翻,我個人的感覺是夜深人靜的時候印象非常深刻,很多知識點很容易就記住了。
三、我習慣手邊放一個小本,初學的一些Linux操作單詞我會寫在上面,詳細用法也會記載,等人或吃飯的時候我會拿來翻一翻,這樣感覺掌握得特別快。對英文頭疼的同學建議堅持看中英文字幕的美劇,比如現在流行的《
生活大爆炸》、《傲骨賢妻》、《權力的游戲》等等,相信英文不會成為學習的阻礙了。
四、實驗過程中的排障一定要注意出錯的原因,比如我近期發現自己PXE安裝的實驗機器,老是帶了一個ifcfg_eth0.bak文件,后來經過仔細分析,發現是由于我的機器是Kickstart安裝,分配的MAC跟原來機器不一致,機器重啟service服務以后就自動的添加了一個ifcfg_eth0.bak文件,知道故障的原因以后就好辦了。
工作中遇到的問題,也應該反反復復排查,千萬不要在沒搞清出錯原因的前提下胡亂猜測,這樣的效果是非常糟糕的。大家可以看下有問題的網卡文件,下面分配的MAC地址實際跟系統網卡自身的MAC地址并不是相匹配的,如下所示:
[root@localhost network-scripts]# cat ifcfg-eth0.bak # Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller DEVICE=eth0 BOOTPROTO=none HWADDR=fe:ff:ff:ff:ff:ff ONBOOT=yes NETMASK=255.255.255.0 IPADDR=192.168.1.120 GATEWAY=192.168.1.1 TYPE=Ethernet |
而實際的網卡MAC地址我們用ifconfig eth0可以查看得到,這個跟上面所列的網卡MAC確實是不一樣的,如下所示:
[root@localhost ~]# ifconfig eth0
eth0 Link encap:Ethernet HWaddr 90:2B:34:87:F3:CD
五、如果遇到復雜的問題或是自己想了很久也沒有答案的知識點,建議可以去看一下別人的博客,學習別人的實驗和心得體會,再融會貫通,吸收了就成了自己的。現在技術論壇的活躍度不高,但很人個人技術含金量還是很高的。這里建議大家一定要做好相關的知識難點的筆記,好記性不如爛筆頭,一個一個小知識,長期堅持下去就是一個很可觀的數值了。
六、實踐出真知,在閱讀別人的技術
文章或著作時,我也發現了不少錯誤之處,這時候千萬不要相信所謂的權威(筆者手上正在閱讀的一本國外專家著作中就存在著不少問題),相信自己的實驗結果,一切以其為判斷依據。
七、遇到新技術或疑難問題,先實驗,再原理,不明白這點的同學先按照我的這種方法試一試,慢慢就明白了。
這些方法貴在堅持,持之以恒的話,肯定是有收獲的。
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
Android SDK 1.5已經將
JUnit包含進來了,重新用的時候還出了一點問題,還是決定寫一篇比較詳細的
文章,供大家和自己以后使用,寫起來也挺方便的,Android下的Junit是對
java下的junit的擴展,殊途同歸,基本類似~
Junit簡介
JUnit是 一個開源的java單元
測試框架。在1997年,由 Erich Gamma 和 Kent Beck 開發完成。這兩個牛人中 Erich Gamma 是 GOF 四人幫之一;Kent Beck 是 XP (Extreme Programming)極限編程創始人(不是Window XP)。俗話說“麻雀雖小,五臟俱全。” JUnit設計的非常小巧,但是功能卻非常強大。Junit在TDD(
Test Driven Development)測試驅動開發中非常常 用,junit是設計比較好的測試框架,Android對junit進行了擴展,使其使用起來更方便省心
JUnit的一些特性:
1) 提供的API可以讓你寫出測試結果明確的可重用
單元測試用例
2) 提供了三種方式來顯示你的測試結果,而且還可以擴展
3) 提供了單元測試用例成批運行的功能
4) 超輕量級而且使用簡單,沒有商業性的欺騙和無用的向導
5) 整個框架設計良好,易擴展
Android Junit Demo
首先GoogleJunit項目,然后新建一個Test Case:
publicclassBookCaseextendsAndroidTestCase {
publicvoid test(){
Log.i("BookCase","測試");
}
}
AndroidTestCase其實本身就是繼承自TestCase,如果這樣運行是沒法運行的,需要到AndroidManifest.xml配置一下:
配置完這個之后還需要application配置一下uses-library:
最后一步就是測試了,右鍵方法Run AS=>Android Junit Test,結果如下:
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
說明:由于條件有限,我這里使用的是同一臺centos的,但教程內容基本上通用。
1.編譯安裝git git安裝教程
2.安裝gitosis
$ yum install python python-setuptools
$ git clone git://github.com/res0nat0r/gitosis.git
$ cd gitosis
$ python setup.py install
2.在開發機器上生成公共密鑰(用來初始化gitosis)
$ ssh-keygen -t rsa #不需要密碼,一路回車就行(在本地操作)
$ scp ~/.ssh/id_rsa.pub root@xxx:/tmp/ # 上傳你的ssh public key到服務器
3.初始化gitosis[服務器端]
$ adduser git # 新增一個git用戶(先添加用戶組 groupadd git)
$ su git # 切換倒git用戶下
$ gitosis-init < /tmp/id_rsa.pub # id_rsa.pub是剛剛傳過來的,注意放在/tmp目錄主要是因為此目錄權限所有人都有定權限的
$ rm /tmp/id_rsa.pub # id_rsa.pub已經無用,可刪除.
4.獲取并配置gitosis-admin [客戶端]
$ git clone git@xxx:gitosis-admin.git # 切換到root用戶并在本地執行,獲取gitosis管理項目,將會產生一個gitosis-admin的目錄,里面有配置文件gitosis.conf和一個 keydir 的目錄,keydir目錄主要存放git用戶名
$ vi gitosis-admin/gitosis.conf # 編輯gitosis-admin配置文件
如果無法git clone的話,可以使用git clone git@xxx:/home/git/repositories/gitosis-admin.git
# 在gitosis.conf底部增加
[group 組名]
writable = 項目名
members = 用戶 # 這里的用戶名字 要和 keydir下的文件名字相一致
# VI下按ZZ(大寫)兩次會執行自動保存并退出,完成后執行
$ cd gitosis-admin
$ git add .
$ git commit -a -m “xxx xx” # 要記住的是,如果每次添加新文件必須執行git add .,或者git add filename,如果沒有新加文件,只是進行修改的話就可以執行此句。
# 修改了文件以后一定要PUSH到服務器,否則不會生效。
$ git push
如果在git push的時候,遇到錯誤“ddress 192.168.0.77 maps to bogon, but this does not map back to the address - POSSIBLE BREAK-IN ATTEMPT!”,解決為修改/etc/hosts文件,將ip地址與主機名對應關系寫進去就可以了。
注意:這里我們并沒有進行任何的修改的,現在只有一個管理git的項目。下面的為新添加項目的配置,大家經常用到的也就是下面的操作的。
新建項目
到此步就算完成gitosis的初始化了。接下來的是新建一個新項目到服務器的操作,如第5步中配置gitosis.conf文件添加的是
[group project1] # 組名稱
writable = project1 # 項目名稱
members = xxx # 用戶名xxx一定要與客戶端使用的用戶名完全一樣,否則無權限操作
$ git commit -a -m “添加新項目project1,新項目的目錄是project1,該項目的成員是xxx“ # “”里的內容自定
$ git push
將新創建的項目提交到git server 上進行登記。以便客戶可以操作新項目.
# 在客戶端創建項目目錄(客戶端,當前用戶為 XXX )
現在回到開發者客戶端,上面創建了一個新項目project1并提交到了git server 。我們這里就創建此項目的信息.注意 項目名稱 project1要與gitosis.conf文件配置一致,
$ mkdir /home/用戶/project1
$ cd /home/用戶/project1
$ git init
$ git add . # 新增文件 留意后面有一個點
$ git commit -a -m “初始化項目project1″
# 然后就到把這個項目放到git server服務器上去.
$ git remote add origin git@xxx:project1.git # xxx為服務器地址
$ git push origin master
# 也可以把上面的兩步合成一步
$ git push git@xxx:project1.git master
說明:如果在執行 git push origin master 的時候,提示以下錯誤: error: src refspec master does not match any. error: failed to push some refs to 'git@192.168.0.77:pro2.git' 這是由于項目為空的原因,我們在項目目錄里新創建一個文件。經過->add -> commit -> push 就可以解決了
$ touch a.txt
$ git add a.txt
$ git commit -a -m 'add a.txt'
$ git push
------------------------------------------------------------------------------------------------ 如果在git clone的時候遇到“
error: cannot run ssh: No such file or directory - cygwin git
”錯誤,則表示本機沒有安裝ssh命令。安裝方法請參考:http://blog.haohtml.com/archives/13313 有時候我們要更換電腦來重新開發項目。這個時候,只需要將id_rsa私鑰放在home目錄里的.ssh目錄里就可以了。(有時候一個人開發多個項目,這時候可能會提示id_rsa文件已經存在。不太清楚這里如何解決???) 續篇:git下添加新項目及用戶
====================================================
三、常見問題
首先確定 /home/git/repositories/gitosis-admin.git/hooks/post-update 為可執行即屬性為 0755
1. git操作需要輸入密碼
原因
公密未找到
解決
上傳id_rsa.pub到keydir并改為'gitosis帳號.pub'形式,如miao.pub。擴展名.pub不可省略
2. ERROR:gitosis.serve.main:Repository read access denied
原因
gitosis.conf中的members與keydir中的用戶名不一致,如gitosis中的members = foo@bar,但keydir中的公密名卻叫foo.pub
解決
使keydir的名稱與gitosis中members所指的名稱一致。 改為members = foo 或 公密名稱改為foo@bar.pub
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters