能測試實例:構建
設計階段完成后,進入構建階段,主要完成設計測試用例、開發測試腳本和確定監控模型。
首先設計測試用例,本實例中設計的測試用例包括登錄和訂票兩個功能,登錄的測試用例見表16-7。
訂票的測試用例見表 16-8。
接著開發測試腳本,開發登錄腳本時需要注意以下幾個問題:
登錄的腳本代碼如下:
Action()
{
/* Registering parameter(s) from source task id 791
// {CSRule_1_UID2}="106229.040745241ftztVfzpciDDDDDDDcHitpQDHH"
// */
//關聯
web_reg_save_param("CSRule_1_UID2",
"LB=userSession value=",
"RB=>",
"Ord=1",
"RelFrameId=1.2.1",
"Search=Body",
LAST);
web_url("WebTours",
"URL=http://127.0.0.1:1080/WebTours/",
"TargetFrame=",
"Resource=0",
"RecContentType=text/html",
"Referer=",
"Snapshot=t1.inf",
"Mode=HTML",
LAST);
web_add_cookie("BAIDUID=EED4BF3C68FCA425464A7B08B3E6721B:FG=1; DOMAIN=passportso.baidu.com");
web_add_cookie("BDUSS=HZ3QTFxaVdJT2NaeVYzMUN4LVFHN2pkbGxSWGZ2fnJmblUybGhuOGtJOUJZRTlPQVFB
QUFBJCQAAAAAAAAAAApBEw8VdxMLYXJpdm5odWFuZwAAAAAAAAAAAAAAAAAAAAAAAAAAAADgGoV0AAA
AAOAahXQAAAAAcF1CAAAAAAAxMC42NS4yMkHTJ05B0ydOZ; DOMAIN=passportso.baidu.com");
web_add_cookie("USERID=379f52fe979c4447da48be6ab312; DOMAIN=passportso.baidu.com");
web_url("q",
"URL=http://passportso.baidu.com/checkuser/q?t=1311397506",
"TargetFrame=",
"Resource=0",
"RecContentType=text/html",
"Referer=",
"Snapshot=t2.inf",
"Mode=HTML",
LAST);
web_add_cookie("BAIDUID=EED4BF3C68FCA425464A7B08B3E6721B:FG=1; DOMAIN=fetch. im.baidu.com");
web_add_cookie("USERID=379f52fe979c4447da48be6ab312; DOMAIN=fetch.im.baidu.com");
web_url("ihaloader",
"URL=http://fetch.im.baidu.com/ihaloader?op=msgcount&charset=gbk&callback=WebIMHistMsg&refer=toolbar&un=arivnhuang",
"TargetFrame=",
"Resource=0",
"RecContentType=text/html",
"Referer=",
"Snapshot=t3.inf",
"Mode=HTML",
LAST);
lr_think_time(6);
//添加檢查點
web_reg_find("Search=Body",
"Text=test11",
"SaveCount=regno",
LAST);
result=web_reg_find("Search=Body",
"Text=test11",
LAST);
web_submit_data("login.pl",
"Action=http://127.0.0.1:1080/WebTours/login.pl",
"Method=POST",
"TargetFrame=",
"RecContentType=text/html",
"Referer=http://127.0.0.1:1080/WebTours/nav.pl?in=home",
"Snapshot=t4.inf",
"Mode=HTML",
ITEMDATA,
"Name=userSession", "Value={CSRule_1_UID2}", ENDITEM,
"Name=userName", "Value={user}", ENDITEM,
"Name=Password", "Value=1", ENDITEM,
"Name=JSFormSubmit", "Value=on", ENDITEM,
"Name=Login.x", "Value=53", ENDITEM,
"Name=Login.y", "Value=13", ENDITEM,
LAST);
//通過檢查點來判斷事務是否成功
if (atoi(lr_eval_string("{regno}"))>=1) {
lr_end_transaction("Login", LR_PASS);
}
else{
lr_end_transaction("Login", LR_FAIL);
}
web_url("SignOff Button",
"URL=http://127.0.0.1:1080/WebTours/welcome.pl?signOff=1",
"TargetFrame=body",
"Resource=0",
"RecContentType=text/html",
"Referer=http://127.0.0.1:1080/WebTours/nav.pl?page=menu&in=home",
"Snapshot=t5.inf",
"Mode=HTML",
LAST);
return 0;
}
最后開發訂票腳本,此時需要注意以下幾個問題:
訂票的腳本代碼如下:
Action()
{
int i; //循環次數變量
int flagno;//標識位,最貴機票是數組中的第幾個值
int min;//最貴機票
char cost[20];//當前機票的價格
char flightcost[20];
char flightnocost[20];
char flightelem[30];//航班
char flightno[30];
web_concurrent_end(NULL);
web_url("Search Flights Button",
"URL=http://127.0.0.1:1080/WebTours/welcome.pl?page=search",
"Resource=0",
"RecContentType=text/html",
"Referer=http://127.0.0.1:1080/WebTours/nav.pl?page=menu&in=home",
"Snapshot=t17.inf",
"Mode=HTTP",
LAST);
web_concurrent_start(NULL);
web_url("reservations.pl",
"URL=http://127.0.0.1:1080/WebTours/reservations.pl?page=welcome",
"Resource=0",
"RecContentType=text/html",
"Referer=http://127.0.0.1:1080/WebTours/welcome.pl?page=search",
"Snapshot=t18.inf",
"Mode=HTTP",
LAST);
web_url("nav.pl_3",
"URL=http://127.0.0.1:1080/WebTours/nav.pl?page=menu&in=flights",
"Resource=0",
"RecContentType=text/html",
"Referer=http://127.0.0.1:1080/WebTours/welcome.pl?page=search",
"Snapshot=t19.inf",
"Mode=HTTP",
LAST);
web_concurrent_end(NULL);
web_url("button_next.gif",
"URL=http://127.0.0.1:1080/WebTours/images/button_next.gif",
"Resource=1",
"RecContentType=image/gif",
"Referer=http://127.0.0.1:1080/WebTours/reservations.pl?page=welcome",
"Snapshot=t20.inf",
LAST);
web_concurrent_start(NULL);
web_url("in_flights.gif",
"URL=http://127.0.0.1:1080/WebTours/images/in_flights.gif",
"Resource=1",
"RecContentType=image/gif",
"Referer=http://127.0.0.1:1080/WebTours/nav.pl?page=menu&in=flights",
"Snapshot=t21.inf",
LAST);
web_url("home.gif",
"URL=http://127.0.0.1:1080/WebTours/images/home.gif",
"Resource=1",
"RecContentType=image/gif",
"Referer=http://127.0.0.1:1080/WebTours/nav.pl?page=menu&in=flights",
"Snapshot=t22.inf",
LAST);
web_concurrent_end(NULL);
//創建機票價格的關聯函數
web_reg_save_param( "WCSParam_Text1", "LB=center>$ ", "RB=", "Ord=All",
"IgnoreRedirections=Yes", "Search=Body", "RelFrameId=1", LAST );
//創建航班的關聯函數
web_reg_save_param( "WCSParam_Text2", "LB=outboundFlight value=", "RB=;", "Ord=All",
"IgnoreRedirections=Yes", "Search=Body", "RelFrameId=1", LAST );
web_submit_data("reservations.pl_2",
"Action=http://127.0.0.1:1080/WebTours/reservations.pl",
"Method=POST",
"RecContentType=text/html",
"Referer=http://127.0.0.1:1080/WebTours/reservations.pl?page=welcome",
"Snapshot=t23.inf",
"Mode=HTTP",
ITEMDATA,
"Name=advanceDiscount", "Value=0", ENDITEM,
"Name=depart", "Value=Frankfurt", ENDITEM,
"Name=departDate", "Value=10/26/2011", ENDITEM,
"Name=arrive", "Value=Denver", ENDITEM,
"Name=returnDate", "Value=10/27/2011", ENDITEM,
"Name=numPassengers", "Value=1", ENDITEM,
"Name=seatPref", "Value=None", ENDITEM,
"Name=seatType", "Value=Coach", ENDITEM,
"Name=.cgifields", "Value=roundtrip", ENDITEM,
"Name=.cgifields", "Value=seatType", ENDITEM,
"Name=.cgifields", "Value=seatPref", ENDITEM,
"Name=findFlights.x", "Value=58", ENDITEM,
"Name=findFlights.y", "Value=5", ENDITEM,
LAST);
//初始化最貴機票,將第一個航班的機票設置為初始化的最貴機票
min=atoi(lr_eval_string("{WCSParam_Text1_1}"));
//初始化標識位,默認設置為 1
flagno=1;
//for 循環所有機票
for(i=2;i <=atoi(lr_eval_string("{WCSParam_Text1_count}"));i++){
sprintf(cost,"{WCSParam_Text1_%d}",i);
//比較最前航班的機票是否大于 max 的值,如果大于 max 的值,則重新對 max 賦值
if(atoi(lr_eval_string(cost)) < min){
min=atoi(lr_eval_string(cost));
lr_error_message("%d",max);
flagno=i;
}
}
sprintf(flightcost,"{WCSParam_Text1_%d}",flagno);
lr_save_string(lr_eval_string(flightcost),"flightnocost");
//通過標識位來確定航班
sprintf(flightelem,"{WCSParam_Text2_%d}",flagno);
lr_save_string(lr_eval_string(flightelem),"flightno");
web_submit_data("reservations.pl_3",
"Action=http://127.0.0.1:1080/WebTours/reservations.pl",
"Method=POST",
"RecContentType=text/html",
"Referer=http://127.0.0.1:1080/WebTours/reservations.pl",
"Snapshot=t24.inf",
"Mode=HTTP",
ITEMDATA,
"Name=outboundFlight", "Value={flightno};{flightnocost};10/26/2011", ENDITEM,
"Name=numPassengers", "Value=1", ENDITEM,
"Name=advanceDiscount", "Value=0", ENDITEM,
"Name=seatType", "Value=Coach", ENDITEM,
"Name=seatPref", "Value=None", ENDITEM,
"Name=reserveFlights.x", "Value=57", ENDITEM,
"Name=reserveFlights.y", "Value=13", ENDITEM,
LAST);
web_submit_data("reservations.pl_4",
"Action=http://127.0.0.1:1080/WebTours/reservations.pl",
"Method=POST",
"RecContentType=text/html",
"Referer=http://127.0.0.1:1080/WebTours/reservations.pl",
"Snapshot=t25.inf",
"Mode=HTTP",
ITEMDATA,
"Name=firstName", "Value=test", ENDITEM,
"Name=lastName", "Value=test", ENDITEM,
"Name=address1", "Value=", ENDITEM,
"Name=address2", "Value=", ENDITEM,
"Name=pass1", "Value=test test", ENDITEM,
"Name=creditCard", "Value=", ENDITEM,
"Name=expDate", "Value=", ENDITEM,
"Name=oldCCOption", "Value=", ENDITEM,
"Name=numPassengers", "Value=1", ENDITEM,
"Name=seatType", "Value=Coach", ENDITEM,
"Name=seatPref", "Value=None", ENDITEM,
"Name=outboundFlight", "Value={flightno};{flightnocost};10/26/2011", ENDITEM,
"Name=advanceDiscount", "Value=0", ENDITEM,
"Name=returnFlight", "Value=", ENDITEM,
"Name=JSFormSubmit", "Value=off", ENDITEM,
"Name=.cgifields", "Value=saveCC", ENDITEM,
"Name=buyFlights.x", "Value=41", ENDITEM,
"Name=buyFlights.y", "Value=17", ENDITEM,
LAST);
web_url("bookanother.gif",
"URL=http://127.0.0.1:1080/WebTours/images/bookanother.gif",
"Resource=1",
"RecContentType=image/gif",
"Referer=http://127.0.0.1:1080/WebTours/reservations.pl",
"Snapshot=t26.inf",
LAST);
return 0;
}
最后確定監控模型,即在測試過程中需要監控哪些信息,本實例的監控模型見表 16-9。
關于“性能測試實例(二):構建”就學習到這里了,每個工作日小編都會更新一個小知識,希望大家多多關注我們,一起來學習喔!
設計階段完成后,進入構建階段,主要完成設計測試用例、開發測試腳本和確定監控模型。
首先設計測試用例,本實例中設計的測試用例包括登錄和訂票兩個功能,登錄的測試用例見表16-7。
本文翻譯自 http://doc.norang.ca/org-mode.html ,原文作者為Bernt Hansen 。由于原文較長,因此會分多篇文章來發布。轉載請標記出處。
rg-mode, 用文本文件管理日常(二)
Org-mode, 用文本文件管理日常(一)
org capture mode取代了 remember mode 用來捕獲任務以及備忘錄。
為使得添加任務更加有效率,我定義了最少的capture模板,曾經我預定義了很多capture模板, 甚至每個org文件都定義一個模板。我通過綁定的快捷鍵 C-c c 來啟動org-capture功能,然后 選擇一個合適的模板,并且將捕獲的內容寫進合適的文件的 * Tasks 分類下面。
我發現我還得將這些capture的任務寫入到不同的org文件的不同位置,因此定義這么多capture 模板根本沒法幫助我。因此我修改了原來的工作流,使用最少的capture模板–這樣我創建任務將會非常快 并且只要重新提取到特定文件一次。當然這樣也節省了我維護我org-capture模板的時間,尤其當需要新加 org文件時候。
當需要添加一個新任務時候,我會將新任務歸入如下幾類模板中的一種:
然后再選擇相應模板。
如下是我的capture 模板的配置:
#+header: :tangle yes
#+begin_src emacs-lisp
(setq org-directory "~/git/org")
(setq org-default-notes-file "~/git/org/refile.org")
;; I use C-c c to start capture mode
(global-set-key (kbd "C-c c") 'org-capture)
;; Capture templates for: TODO tasks, Notes, appointments, phone calls, meetings, and org-protocol
(setq org-capture-templates
(quote (("t" "todo" entry (file "~/git/org/refile.org")
"* TODO %?\n%U\n%a\n" :clock-in t :clock-resume t)
("r" "respond" entry (file "~/git/org/refile.org")
"* NEXT Respond to %:from on %:subject\nSCHEDULED: %t\n%U\n%a\n" :clock-in t :clock-resume t :immediate-finish t)
("n" "note" entry (file "~/git/org/refile.org")
"* %? :NOTE:\n%U\n%a\n" :clock-in t :clock-resume t)
("j" "Journal" entry (file+datetree "~/git/org/diary.org")
"* %?\n%U\n" :clock-in t :clock-resume t)
("w" "org-protocol" entry (file "~/git/org/refile.org")
"* TODO Review %c\n%U\n" :immediate-finish t)
("m" "Meeting" entry (file "~/git/org/refile.org")
"* MEETING with %? :MEETING:\n%U" :clock-in t :clock-resume t)
("p" "Phone call" entry (file "~/git/org/refile.org")
"* PHONE %? :PHONE:\n%U" :clock-in t :clock-resume t)
("h" "Habit" entry (file "~/git/org/refile.org")
"* NEXT %?\n%U\n%a\nSCHEDULED: %(format-time-string \"%<<%Y-%m-%d %a .+1d/3d>>\")\n:PROPERTIES:\n:STYLE: habit\n:REPEAT_TO_STATE: NEXT\n:END:\n"))))
#+end_src
capture mode能夠對新建任務自動處理計時與終止計時。該功能是capture自帶功能并不需要新添加 代碼來實現該功能。當我啟動capture mode創建的任務,任務通過指定 :clock-in t 就可以自動開始計時,當任務通過快捷鍵 C-c C-c 將任務寫入文件時候,會重新從原來計時的任務開始計時。
通過capture mode創建的那種快速完成的計時任務,當短時間結束時(通常少于1分鐘) 會在我的任務里邊 產生一個空的計時抽屜,而這個空的計時抽屜不是特別有用。因此我會將如下計時抽屜刪除掉。
#+begin_src org :exports src
,* TODO New Capture Task
:LOGBOOK:
:END:
[2010-05-08 Sat 13:53]
#+end_src
我使用如下自定義的函數來移除這些在 LOGBOOK 生成的空的計時日志。
#+header: :tangle yes
#+begin_src emacs-lisp
;; Remove empty LOGBOOK drawers on clock out
(defun bh/remove-empty-drawer-on-clock-out ()
(interactive)
(save-excursion
(beginning-of-line 0)
(org-remove-empty-drawer-at "LOGBOOK" (point))))
(add-hook 'org-clock-out-hook 'bh/remove-empty-drawer-on-clock-out 'append)
#+end_src
我只使用一個org 文件來作為我capture模板的目標文件。
我會在這個命名為 refine.org 文件中存備忘,任務,回電以及org-protocol相關的任務. 曾經也用過多個文件,但是 發現多個文件并沒有什么優勢。
通常這個文件是空的,除了第一行創建了 REFILE 標簽。
這個文件唯一的一行永久存在的內容如下:
#+begin_src org :exports src
#+FILETAGS: REFILE
#+end_src
好了, 當我正在做些事情時候-我需要記住它。我不想停下手上的事。我可能在孵化一個項目, 通常我不希望脫離當前聚焦的事情,但是同時我又不想錯過新來的的事情。
這時我該怎么辦?通過 C-c c 啟動capture mode然后選擇 t ,然后我的buffer中會產 生一個如下格式的任務:
#+begin_src org :exports src
,* TODO
[2010-08-05 Thu 21:06]
[[file:~/git/org-mode-doc/org-mode.org::*Capture%20Tasks%20is%20all%20about%20being%20FAST][Capture Tasks is all about being FAST]]
#+end_src
在新生成的TODO任務中寫入新來的任務細節,然后 C-c C-c 這條任務就會寫入refile.org文件。然后我就可以繼續當前手上工作,同時之前任務也不會丟失,我此時也不必花精力去考慮新來的任務。
對于capture任務note更新時間會記錄下來。capture模板自動設置計時以及停止計時。這對突然的 打斷以及回電話非常有用。
重定向任務很簡單。當我的refile.org文件中通過capture mode積累了一堆任務之后。我需要將這些任務移動到正確的org文件的合適分類中。我所有的在用的org文件都通過 org-agenda-files 變量定義,都可以在agenda中顯示。
我有時候會在refile.org文件中累積長達1周的capture任務。在agenda 視圖中顯示出來的當日任務,我通常當天就重定向到其他文件中。我喜歡 保持重定向任務列表是空的。
為重定向任務到新的org文件中,你需要知道這些任務應該重定向到哪里。
我的設置中,會將 org-agenda-files 定義的文件以及當前文件作為重定向的目標。
我現在使用IDO來完成目標查找。我發現IDO處理起來比之前的設置更加快。剛開始我并不喜歡IDO, 但是當看了些相關的文檔后,了解到 C-SPEC 可以限制目標搜搜數量,我發現它比我之前設置好 用多了。現在,當我想重定向refile文件中的任務時候,我只需要執行快捷鍵 C-c C-w 啟動重定向流程, 然后輸入一些匹配字段,然后執行 C-SPC 限制到匹配到當前列表,然后繼續查找其他目標。 C-j 可以選擇 當前的作為目標。我喜歡這樣。我通常顯示所有的目標文件大綱列表,因此我可以擁有相同的頭在不同子樹下 或者不同項目中,并且當重定向時也能夠方便區分。
當前我會將 DONE 狀態任務作為有效重定向任務。這樣可以保證重定向目標合適大小。
我的重定向配置如下:
#+header: :tangle yes
#+begin_src emacs-lisp
; Targets include this file and any file contributing to the agenda - up to 9 levels deep
(setq org-refile-targets (quote ((nil :maxlevel . 9)
(org-agenda-files :maxlevel . 9))))
; Use full outline paths for refile targets - we file directly with IDO
(setq org-refile-use-outline-path t)
; Targets complete directly with IDO
(setq org-outline-path-complete-in-steps nil)
; Allow refile to create parent tasks with confirmation
(setq org-refile-allow-creating-parent-nodes (quote confirm))
; Use IDO for both buffer and file completion and ido-everywhere to t
(setq org-completion-use-ido t)
(setq ido-everywhere t)
(setq ido-max-directory-size 100000)
(ido-mode (quote both))
; Use the current window when visiting files and buffers with ido
(setq ido-default-file-method 'selected-window)
(setq ido-default-buffer-method 'selected-window)
; Use the current window for indirect buffer display
(setq org-indirect-buffer-display 'current-window)
;;;; Refile settings
; Exclude DONE state tasks from refile targets
(defun bh/verify-refile-target ()
"Exclude todo keywords with a done state from refile targets"
(not (member (nth 2 (org-heading-components)) org-done-keywords)))
(setq org-refile-target-verify-function 'bh/verify-refile-target)
#+end_src
為了將任務重定向到 norang.org 文件,我通常將光標移到需要重定向的任務上,然后執行 C-c C-w ,然后執行 nor C-SPC sys RET 就可以完成了。IDO 補全模式讓定位目標非常方便。
需要重定向的任務都在agenda的特定塊中。為快速找到需要重定向的任務,我先通過 F12 SPC 打開 agenda視圖,然后滾動到第二節: Tasks to Refile . 該視圖中顯示所有的任務(即使有些任務已經 被標記為=donw=狀態)
在agenda中批量將任務重定向到相同位置也是非常方便。只要列出所有需要批量重定向任務,然后通過 m 標記這些任務,最后執行 B r 將會將所有標記的task重定向到新的目標。通常,我也會通過執行 C-2 C-c C-w 重定向當前任務作為當前計時任務的子任務.
執行重定向耗時通常在1分鐘以內,因此我每天都會重定向好幾次。
我通常在大部分org 文件中保留 * Notes 類型。備忘通常通過capture模板創建,同時會 給任務加上 NOTE 標簽,由于有標簽,所以方便通過agenda在不同文件快速查找。
備忘首先會創建在 refile.org 文件中,然后通過重定向功能重定向到合適項目文件中。有些項目 相關備忘會重定向到相應的項目任務下面,而非 * NOTES 大綱中。這種備忘通常只和該項目相關, 通常項目結束后就沒太大用處了–當歸檔項目時候,刪除這些備忘也沒什么關系。
回電以及會議任務也是通過capture mode來創建的。在通過capture mode 模板創建這種任務時 會啟動計時,當回電完成或者會議結束,計時也會結束。
回電以及會議任務也是生成到 refile.org 中,然后通過重定向功能定向到合適的位置。有些是項目相關的回電,我們也希望在合適的分類中跟蹤。我會重定向回電以及會議任務到合適 項目中,這樣跟蹤以及報告會更加精確。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。