【功能】
WebScarab是一個用來分析使用HTTP和HTTPS協(xié)議的應(yīng)用程序框架。其原理很簡單,WebScarab可以記錄它檢測到的會話內(nèi)容(請求和應(yīng)答),并允許使用者可以通過多種形式來查看記錄。WebScarab的設(shè)計目的是讓使用者可以掌握某種基于HTTP(S)程序的運(yùn)作過程;可以用它來調(diào)試程序中較難處理的bug,也可以幫助安全專家發(fā)現(xiàn)潛在的程序漏洞。
【適用對象】
分析使用HTTP和HTTPS協(xié)議的應(yīng)用程序框架
1.1.1 工具安裝
WebScarab需要在
java 環(huán)境下運(yùn)行,因此在安裝WebScarab前應(yīng)先安裝好java環(huán)境(JRE或JDK均可)。
安裝好jdk后,右擊安裝文件:webscarab-installer-20070504-1631.jar 選擇“打開方式”如下圖:
然后進(jìn)入安裝界面,下一步下一步安裝即可。
1.1.2 功能原理
webscarab工具的主要功能:它可以獲取客戶端提交至服務(wù)器的http請求消息,并以圖形化界面顯示,支持對http請求信息進(jìn)行編輯修改。
原理:webscarab工具采用
web 代理原理,客戶端與web服務(wù)器之間的http請求與響應(yīng)都需要經(jīng)過webscarab進(jìn)行中轉(zhuǎn),webscarab將收到的http請求消息進(jìn)行分析,并將分析結(jié)果圖形化顯示,如下圖:
可以用于驗證當(dāng)客戶端對輸入有限制時(如長度限制、輸入字符集的限制等),可以使用此種方法繞過客戶端驗證服務(wù)端是否對輸入有限制。
1.1.3 工具使用
下面將主要介紹如何使用webscarab工具對post請求進(jìn)行參數(shù)篡改
1、 運(yùn)行WebScarab
WebScarab有兩種顯示模式:Lite interface和full-featured interface,可在Tools菜單下進(jìn)行模式切換,需要重啟軟件生效,修改http請求信息需要在full-featured interface下進(jìn)行。
2、 點(diǎn)擊Proxy標(biāo)簽頁->Manual Edit標(biāo)簽頁
3、 選中Intercept requests
在Methods中列舉了http1.1協(xié)議所有的請求方法,用來選擇過濾,如我們選擇了post,那WebScarab只能對post請求的http消息進(jìn)行篡改。
4、 打開IE瀏覽器的屬性,進(jìn)入連接》局域網(wǎng)設(shè)置,在代理地址中配置host為127.0.0.1或localhost,port為8008
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
Text-to-speech function is limited to 100 characters
快速上手
如果你對
Selenium 自動化測試 已經(jīng)非常熟悉,你僅僅需要一個快速上手來使程序運(yùn)行起來。本章節(jié)的內(nèi)容能滿足不同的技術(shù)層次,但是如果你僅僅需要一個可以快速上手的指引,那么就顯得有點(diǎn)多。如果是這樣,你可以參考 Selenium Wiki 的相關(guān)
文章 。
什么是 Selenium-Grid ?
Selenium-Grid 允許你在多臺機(jī)器的多個瀏覽器上并行的進(jìn)行測試,也就是說,你可以同時運(yùn)行多個測試。本質(zhì)上來說就是,Selenium-Grid 支持分布式的測試執(zhí)行。它可以讓你的測試在一個分布式的執(zhí)行環(huán)境中運(yùn)行。
何時需要使用
通常,以下兩種情況你都會需要使用 Selenium-Grid。
在多個瀏覽器中運(yùn)行測試,在多個版本的瀏覽器中進(jìn)行測試,或在不同
操作系統(tǒng) 的瀏覽器中進(jìn)行測試。
減少測試運(yùn)行時間。
Selenium-Grid 通過使用多臺機(jī)器并行地運(yùn)行測試來加速測試的執(zhí)行過程。例如,如果你有一個包含100個
測試用例 的測試套件,你使用 Selenium-Grid 支持4臺不同的機(jī)器(虛擬機(jī)或?qū)嶓w機(jī)均可)來運(yùn)行那些測試,同僅使用一臺機(jī)器相比,你的測試所需要的運(yùn)行時間大致為其 1/4。對于大型的測試套件和那些會進(jìn)行大量數(shù)據(jù)校驗的需要長時間運(yùn)行的測試套件來說,這將節(jié)約很多時間。有些測試套件可能要運(yùn)行好幾小時。另一個需要縮短套件運(yùn)行時間的原因是開發(fā)者檢入(check-in)AUT 代碼后,需要縮短測試的運(yùn)行周期。越來越多的團(tuán)隊使用
敏捷 開發(fā),相比整夜整夜的等待測試通過,他們希望盡快地看到測試反饋。
Selenium-Grid 也可以用于支持多執(zhí)行環(huán)境的測試運(yùn)行,典型的,同時在多個不同的瀏覽器中運(yùn)行。例如,Grid 的虛擬機(jī)可以安裝測試必須的各種瀏覽器。于是,機(jī)器 1 上有 ie8,機(jī)器 2 上有 ie9,機(jī)器 3 上有最新版的 chrome,而機(jī)器 4 上有最新版的 firefox。當(dāng)測試套件運(yùn)行時,Selenium-Grid 可以使測試在指定的瀏覽器中運(yùn)行,并且接收每個瀏覽器的運(yùn)行結(jié)果。
另外,我們可以擁有一個裝有多個類型和版本都一樣的瀏覽器 Grid。例如,一個 Grid 擁有 4 臺機(jī)器,每臺機(jī)器可以運(yùn)行 3 個 firefox 12 實(shí)例,形成一個 firefox 的服務(wù)農(nóng)場。當(dāng)測試套件運(yùn)行時,每個傳遞給 Selenium-Grid 的測試都被指派給下一個可用的 firefox 實(shí)例。通過這種方式,我們可以使得同時有 12 個測試在并行的運(yùn)行以完成測試,顯著地縮短了測試完成需要的時間。
Selenium-Grid 非常靈活。以上兩個例子可以聯(lián)合起來使用,這樣可以就可以使得不同類型和版本的瀏覽器有多個可運(yùn)行實(shí)例。使用這樣的配置,既并行地執(zhí)行測試,同時又可以測試多個瀏覽器類型和版本。
Selenium-Grid 2.0
Selenium-Grid 2.0 是在編寫本文時(5/26/2012)已發(fā)布的最新版本。它同版本 1 有很多不同之處。在 2.0 中,Selenium-Grid 和 Selenium-RC 服務(wù)端進(jìn)行了合并。現(xiàn)在,你僅需要下載一個 jar 包就可以獲得它們。
Selenium-Grid 1.0
版本 1 是 Selenium-Grid 的第一個發(fā)布版本。如果你是一個 Selenium-Grid 新手,你應(yīng)該選擇版本 2 。新版本已經(jīng)在原有基礎(chǔ)上進(jìn)行了更新,頁增加了一些新特性,并且支持 Selenium-WebDriver。一些老的系統(tǒng)可能仍然在使用版本 1.關(guān)于 Selenium-Grid 版本 1 的信息可以參考 Selenium-Grid website
Selenium-Grid 的 Hub 和 Nodes 是如何
工作 的?
Grid 由一個中心和一到多個節(jié)點(diǎn)組成。兩者都是通過 selenium-server.jar 啟動。在接下來的章節(jié)中,我們列出了一些例子。
中心接收要執(zhí)行的測試信息,包括在哪些平臺和瀏覽器執(zhí)行等。它知道每個注冊了的節(jié)點(diǎn)的配置。根據(jù)測試信息,它會選擇符合需求的節(jié)點(diǎn)進(jìn)行測試。一旦選定了一個節(jié)點(diǎn),測試腳本就會初始化 Selenium 命令,并且由重心發(fā)送給選定的要運(yùn)行測試的節(jié)點(diǎn)。這個節(jié)點(diǎn)會啟動瀏覽器,然后在瀏覽器中執(zhí)行這個 AUT 的 Selenium 命令。
我們提供了一些圖標(biāo)來演示其原理。第二張圖標(biāo)是用以說明 Selenium-Grid 1 的,版本 2 也適用并且對于我們的描述是一個很好的說明。唯一的區(qū)別在于相關(guān)術(shù)語。使用“Selenium-Grid 節(jié)點(diǎn)”替換“Selenium Remote Control”即符合我們對 Selenium-Grid 2 的描述。
下載
下載過程很簡單。從 SeleniumHq 站點(diǎn)的下載頁面下載 Selenium-Server jar 包。你需要的鏈接在“Selenium-Server (以前是 Selenium-RC)”章節(jié)中。
將它存放到任意文件夾中。你需要確保機(jī)器上正確的安裝了
java 。如果 java 沒有正常運(yùn)行,檢查你系統(tǒng)的 path 變量是否包含了 java.exe 的路徑。
啟動 Selenium-Grid
由于節(jié)點(diǎn)對中心有依賴,所以你通常需要先啟動一個中心。這也不是必須的,因為節(jié)點(diǎn)可以識別其中心是否已經(jīng)啟動,反之亦然。作為教程,我們建議你先啟動中心,否則會顯示一些錯誤信息,你應(yīng)該不會想在第一次使用 Selenium-Grid 的時候就看到它們。
啟動中心
通過在命令行執(zhí)行以下命令,可以啟動一個使用默認(rèn)設(shè)置的中心。所有平臺可用,包括 Windows Linux, 或 MacOs 。
java -jar selenium-server-standalone-2.21.0.jar -role hub
我們將在接下來的章節(jié)中解釋各個參數(shù)。注意,你可能需要修改上述命令中 jar 包的版本號,這取決于你使用的 selenium-server 的版本。
啟動節(jié)點(diǎn)
通過在命令行執(zhí)行以下命令,可以你懂一個使用默認(rèn)設(shè)置的節(jié)點(diǎn)。
java -jar selenium-server-standalone-2.21.0.jar -role node -hub http://localhost:4444/grid/register
該操作假設(shè)中心是使用默認(rèn)設(shè)置啟動的。中心用于監(jiān)聽請求使用的默認(rèn)端口號為 4444,這就是為什么端口 4444 被用于中心 url 中。同時“localhost”假定你的節(jié)點(diǎn)和中心運(yùn)行在同一臺機(jī)器上。對于新手來說,這是最簡單的方式。如果要在兩臺不同的機(jī)器上運(yùn)行中心和節(jié)點(diǎn),只需要將“localhost”替換成中心所在機(jī)器的 hostname 即可。
警告: 確保運(yùn)行中心和節(jié)點(diǎn)的機(jī)器均已關(guān)閉防火墻,否則你將看到一個連接錯誤。
配置 Selenium-Grid
默認(rèn)配置
JSON 配置文件
通過命令行選項配置
中心配置
通過指定 -role hub 即以默認(rèn)設(shè)置啟動中心:
java -jar selenium-server-standalone-2.21.0.jar -role hub
你將看到以下日志輸出:
Jul 19, 2012 10:46:21 AM org.openqa.grid.selenium.GridLauncher main
INFO: Launching a selenium grid server
2012-07-19 10:46:25.082:INFO:osjs.Server:jetty-7.x.y-SNAPSHOT
2012-07-19 10:46:25.151:INFO:osjsh.ContextHandler:started o.s.j.s.ServletContextHandler{/,null}
2012-07-19 10:46:25.185:INFO:osjs.AbstractConnector:Started SocketConnector@0.0.0.0:4444
指定端口
中心默認(rèn)使用的端口是 4444 。這是一個 TCP/IP 端口,被用于監(jiān)聽客戶端,即自動化測試腳本到 Selenium-Grid 中心的連接。如果你電腦上的另一個應(yīng)用已經(jīng)占用這個接口,或者你已經(jīng)啟動了一個 Selenium-Server,你將看到以下輸出:
10:56:35.490 WARN - Failed to start: SocketListener0@0.0.0.0:4444
Exception in thread "main" java.net.BindException: Selenium is already running on port 4444. Or some other service is.
如果看到這個信息,你可以關(guān)掉在使用端口 4444 的進(jìn)程,或者告訴 Selenium-Grid 使用一個別的端口來啟動中心。-port 選項用于修改中心的端口:
java -jar selenium-server-standalone-2.21.0.jar -role hub -port 4441
即使已經(jīng)有一個中心運(yùn)行在這臺機(jī)器上,只要它們不使用同一個端口,就能正常工作。
你可能想知道哪個進(jìn)程使用了 4444 端口,這樣你就可以讓中心使用這個默認(rèn)端口。使用以下命令可以查看你機(jī)器上所有運(yùn)行程序使用的端口:
netstat -a
Unix/Linux, MacOs 和 Windows 均支持此命令,只是在 Windows 中 -a 參數(shù)為必須的。基本上,你需要顯示進(jìn)程 id 和端口。在 Unix 中,你可以通過管道 “grep” 輸出那些你關(guān)心的端口相關(guān)的條目。
節(jié)點(diǎn)配置
時間參數(shù)
獲取命令行幫助
Selenium-Server 提供了一個可選項列表,每個選項都有一個簡短的描述。目前(2012夏),命令行幫助還有一些奇怪,但是如果你知道如何去找、如何解讀信息會對你很有幫助。
Selenium-Server 提供了兩種不同的功能,Selenium-RC server 和 Selenium-Grid。它們是兩個不同的團(tuán)隊編寫的,所以每個功能的命令行幫助被放置在不同的地方。因此,對于新手來說,在初次使用任意一個功能時,幫助都不是那么顯而易見。
如果你僅傳遞一個 -h 選項,你將看到 Selenium-RC Server 的可選項而不是 Selenium-Grid 的。
java -jar selenium-server-standalone-2.21.0.jar -h
上述代碼將顯示 Selenium-RC server 選項。如果你想看到 Selenium-Grid 的命令行幫助,你需要先使用 -hub 或 -node 選項告訴 Selenium-Server 你想看的是關(guān)于 Selenium-Grid 的,然后再追加 -h 選項。
java -jar selenium-server-standalone-2.21.0.jar -role node -h
對于這個問題,你還可以給 -role node 傳遞一個垃圾參數(shù):
java -jar selenium-server-standalone-2.21.0.jar -role node xx
你將先看到 “INFO...” 和一個 “ERROR”,在其后你將看到 Selenium-Grid 的命令行選項。我們沒有列出這個命令的所有輸出,因為它實(shí)在太長了,這個輸出的最初幾行看起來如下:
Jul 19, 2012 10:10:39 AM org.openqa.grid.selenium.GridLauncher main
INFO: Launching a selenium grid node
org.openqa.grid.common.exception.GridConfigurationException: You need to specify a hub to register to using -hubHost X -hubPort 5555. The specified config was -hubHost null -hubPort 4444
at org.openqa.grid.common.RegistrationRequest.validate(RegistrationRequest.java:610)
at org.openqa.grid.internal.utils.SelfRegisteringRemote.startRemoteServer(SelfRegisteringRemote.java:88)
at org.openqa.grid.selenium.GridLauncher.main(GridLauncher.java:72)
Error building the config :You need to specify a hub to register to using -hubHost X -hubPort 5555. The specified config was -hubHost null -hubPort 4444
Usage :
-hubConfig:
(hub) a JSON file following grid2 format.
-nodeTimeout:
(node) <XXXX> the timeout in seconds before the hub
automatically ends a test that hasn't had aby activity than XX
sec.The browser will be released for another test to use.This
typically takes care of the client crashes.
常見錯誤
Unable to acess the jarfile
Unable to access jarfile selenium-server-standalone-2.21.0.jar
無論是啟動中心還是節(jié)點(diǎn)都有可能產(chǎn)生這個錯誤。這意味著 java 無法找到 selenium-server jar 包。你需要從 selenium-server-XXXX.jar 文件存放在目錄運(yùn)行命令或者指定 jar 包的完整路徑。
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
Text-to-speech function is limited to 100 characters
一、體系架構(gòu)
1.C/S:客戶端+服務(wù)器端,如QQ、單機(jī)版記事本、office等,所用語言:VB、C++、C、C#、JAVA、PB、D…等數(shù)組語言,C和S都是自己測,且復(fù)雜度較高。擴(kuò)展性差。
補(bǔ):軟件質(zhì)量包括五種質(zhì)量:內(nèi)部質(zhì)量、外部質(zhì)量、過程質(zhì)量、使用質(zhì)量、情感質(zhì)量(從使用質(zhì)量提取出來的,易用性的、用戶體驗的老師稱為情感質(zhì)量)。
B/S:瀏覽器+服務(wù)器,S如tomcat、IIS,所用語言:HTML、ASP、PHP、JSP等腳本語言,B和S都是成熟的產(chǎn)品,不需測。范圍廣。擴(kuò)展性好,便于用戶訪問,但是安全性較差。可看到后綴,根據(jù)后綴知道其架構(gòu),即知道什么語言開發(fā),可能使用的服務(wù)器是什么,可能使用的
數(shù)據(jù)庫 是什么,可能使用的服務(wù)器的
操作系統(tǒng) 是什么。便于測試。
機(jī)房包括:HTTP(只做請求的轉(zhuǎn)發(fā),不做請求的具體處理,做負(fù)載均衡的)、
Web Server(網(wǎng)絡(luò)服務(wù))、APP Server(應(yīng)用服務(wù))、DB Server(數(shù)據(jù)庫服務(wù)器)。
嵌入式應(yīng)用系統(tǒng):如投影儀,里面裝有數(shù)控類的代碼,也是程序,對其需用模擬器來進(jìn)行測試,稱為嵌入式系統(tǒng)。
如今很多企業(yè)都是C/S和B/S合并起來做,核心關(guān)鍵的用B/S做,對外公布的用C/S做,兩者之間留接口即可。涉及軍工類的都是C/S架構(gòu)。
2.web服務(wù)器:在B/S架構(gòu)開發(fā)平臺:J2EE(Java開發(fā),包括:J2EE企業(yè)級,是C/S系統(tǒng);J2ME微型平臺,是嵌入式系統(tǒng);J2SE標(biāo)準(zhǔn)平臺,是桌面型系統(tǒng)、.net(C#,
微軟 開發(fā),是站點(diǎn)開發(fā),應(yīng)用于電子商務(wù))、LAMP(php開發(fā),Linux+Apache+MySQL+php)
SUN: 后臺Java,前臺jsp
常用的web服務(wù)器:Apache、Tomcat、IIS、jboss、Resin、weblogic、WebSphere
3.DB Server數(shù)據(jù)庫服務(wù)器:全部基于
SQL 語言(結(jié)構(gòu)化查詢語言),包括:
MySQL 、SQLServer、
Oracle 、Sybase、DB2(后三者過了安全認(rèn)證即五星認(rèn)證,較厲害)
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
Text-to-speech function is limited to 100 characters
karma作為angular測試runner出現(xiàn),如果你使用過karma一定感受到這很不錯的javascript測試runner。簡單干凈的配置文件karma.config.js,以及karma init一些快捷的配置command。以及整套
測試 套件,如html2js,coverage。對于angular單元測試karma就是一個全生態(tài)的測試套件,能夠簡潔快速的搭建整個測試流程。
本文將嘗試運(yùn)用karma作為jQuery單元測試runner。對于jQuery這種DOM操作的框架,有時難于分離view邏輯,以及ajax這種外部資源的mock,所以比較難于實(shí)施對jQuery程序的TDD開發(fā)。
jasmime測試套件
對于jasmine測試框架為了解決這些問題有兩個插件jasmine-jquery和jasmine-ajax。
jasmine-jquery
jasmine-jQuery主要解決加載測試所需的DOM元素,為
單元測試 構(gòu)建前置環(huán)境。jasmine-jQuery加載DOM方法:
jasmine.getFixtures().fixturesPath = 'base path';
loadFixtures('myfixture.html');
jasmine.getFixtures().load(...);
這里的loadFixtures需要真實(shí)ajax獲取html fixtures所以我們需要提前host html fixtures。jasmine-jQuery還框架了一些有用的matchers,如toBeChecked, toBeDisabled, toBeFocused,toBeInDOM……
jasmine-ajax
jasmine-ajax則是對于一般ajax測試的mock框架,其從底層xmlhttprequest實(shí)施mock。所以讓我們能很容易實(shí)施對于jQuery的$.ajax,$.get…mock。如
beforeEach(function() {
jasmine.Ajax.requests.when = function (url) {
return this.filter("/jquery/ajax")[0];
};
jasmine.Ajax.install();
});
it("jquery ajax success with getResponse", function() {
var result;
$.get("/jquery/ajax").success(function(data) {
result = data;
});
jasmine.Ajax.requests.when("/jquery/ajax").response({
"status": 200,
"contentType": 'text/plain',
"responseText": 'data from mock ajax'
});
expect(result).toEqual('data from mock ajax');
});
afterEach(function() {
jasmine.Ajax.uninstall();
});
對于jasmine-ajax是實(shí)施mock之前一定需要jasmine.Ajax.install(),以及測試完成后需要jasmine.Ajax.uninstall();jasmine-ajax在install后會把所有的ajax mock掉,所以如果有需要真實(shí)ajax的需要在install之前完成,如jasmine-jQuery加載view loadFixtures。
運(yùn)用karma runner
我們已經(jīng)了解了jasmine測試的兩個框架jasmine-jQuery和jasmine-ajax,所以運(yùn)用karma作為runner,我們需要解決的問題就是把他們和karma集成在一起。
所以分為以下幾步: 1:karma中引入jasmine-jQuery和jasmine-ajax(可以利用bowerinstall) 2:host 測試的html fixtures。 3:加載html fixtures 與install ajax之前。
對于host 文件karma提供了pattern模式,所以karma配置為:
files: [
{
pattern: 'view/**/*.html',
watched: true,
included: false,
served: true
},
'bower_components/jquery/dist/jquery.js',
'bower_components/jasmine-jquery/lib/jasmine-jquery.js',
'bower_components/jasmine-ajax/lib/mock-ajax.js',
'src/*.js',
'test/*.js'
],
這里需要注意karma自帶的jasmine是低版本的,所以我們需要npm install karma-jasmine@2.0獲取最新的karma-jasmine插件。
我們就可以完成了karma的配置,我們可以簡單測試我們的配置:demo on github.
測試html fixtures加載:
describe('console html content', function() {
beforeEach(function() {
jasmine.getFixtures().fixturesPath = 'base/view/';
loadFixtures("index.html");
});
it('index html', function() {
expect($("h2")).toBeInDOM();
expect($("h2")).toContainText("this is index page");
});
})
測試mock ajax:
describe('console html content', function() {
beforeEach(function() {
jasmine.Ajax.requests.when = function(url) {
return this.filter("/jquery/ajax")[0];
};
jasmine.Ajax.install();
});
it('index html', function() {
expect($("h2")).toBeInDOM();
expect($("h2")).toContainText("this is index page");
});
it("ajax mock", function() {
var doneFn = jasmine.createSpy("success");
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(args) {
if (this.readyState == this.DONE) {
doneFn(this.responseText);
}
};
xhr.open("GET", "/some/cool/url");
xhr.send();
expect(jasmine.Ajax.requests.mostRecent().url).toBe('/some/cool/url');
expect(doneFn).not.toHaveBeenCalled();
jasmine.Ajax.requests.mostRecent().response({
"status": 200,
"contentType": 'text/plain',
"responseText": 'awesome response'
});
expect(doneFn).toHaveBeenCalledWith('awesome response');
});
it("jquery ajax success with getResponse", function() {
var result;
getResponse().then(function(data){
result = data;
});
jasmine.Ajax.requests.when("/jquery/ajax").response({
"status": 200,
"contentType": 'text/plain',
"responseText": 'data from mock ajax'
});
expect(result).toEqual('data from mock ajax');
});
it("jquery ajax error", function() {
var status;
$.get("/jquery/ajax").error(function(response) {
status = response.status;
});
jasmine.Ajax.requests.when("/jquery/ajax").response({
"status": 400
});
expect(status).toEqual(400);
});
afterEach(function() {
jasmine.Ajax.uninstall();
});
})
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
Text-to-speech function is limited to 100 characters
一周時間過去了,斷斷續(xù)續(xù)學(xué)習(xí)selenium 也有幾個小時了;今天細(xì)想一下學(xué)習(xí) 效率不高的原因在哪,總結(jié)出以下幾點(diǎn): 1、求“進(jìn)”心切——總想一步到位,搭建好環(huán)境,開始動手寫用例。
2、學(xué)習(xí)深度不夠——同樣想著快速瀏覽一遍某大神、高手的日志,教程什么的很立即動手復(fù)制,其實(shí)很多基礎(chǔ)環(huán)境不一樣,無法全部照搬。
3、學(xué)習(xí)時間太少——這個是最為關(guān)鍵的點(diǎn),統(tǒng)計一下,一周下來,花在學(xué)習(xí)Selenium上的時間不過3-5小時,而且時間分布在12點(diǎn)到2點(diǎn)之間,效率也最低下。
兩天前弄出來的SELENIUM IDE for firefox已經(jīng)可以進(jìn)行錄制回放功能,做一些最為簡單的單線流程錄制。但一直無法將用例轉(zhuǎn)換的JAVA代碼編譯通過,報錯也無法定位與解決,被阻塞了兩天時間 。
Java for selenium 做WEB測試應(yīng)具有的知識體系,大致如下(自己感受):
1、JAVA基礎(chǔ),與
JUnit (不了解)
2、selenium的JAVA API及selenium基本知識(摸不著北)
通過分析上述的幾點(diǎn)要求后,發(fā)現(xiàn)自己在基礎(chǔ)上還是非常薄弱,不能一味的追求快;而是需要一邊夯實(shí)基礎(chǔ)、一邊開闊視野、一邊提升;推動整體向前進(jìn)步。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" />
<title>hyddd</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">hyddd</td></tr>
</thead><tbody>
<tr>
<td>open</td>
<td>/</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>id=kw1</td>
<td></td>
</tr>
<tr>
<td>type</td>
<td>id=kw1</td>
<td>hyddd</td>
</tr>
<tr>
<td>click</td>
<td>id=su1</td>
<td></td>
</tr>
</tbody></table>
</body>
</html>
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
Text-to-speech function is limited to 100 characters
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
Text-to-speech function is limited to 100 characters
通常我們通過終端連接到
linux 系統(tǒng)后執(zhí)行ulimit -n 命令可以看到本次登錄的session其文件描述符的限制,如下:
$ulimit -n
1024
當(dāng)然可以通過ulimit -SHn 102400 命令來修改該限制,但這個變更只對當(dāng)前的session有效,當(dāng)斷開連接重新連接后更改就失效了。
如果想永久變更需要修改/etc/security/limits.conf 文件,如下:
vi /etc/security/limits.conf
* hard nofile 102400
* soft nofile 102400
保存退出后重新登錄,其最大文件描述符已經(jīng)被永久更改了。
這只是修改用戶級的最大文件描述符限制,也就是說每一個用戶登錄后執(zhí)行的程序占用文件描述符的總數(shù)不能超過這個限制。
系統(tǒng)級的限制
它是限制所有用戶打開文件描述符的總和,可以通過修改內(nèi)核參數(shù)來更改該限制:
sysctl -w fs.file-max=102400
使用sysctl命令更改也是臨時的,如果想永久更改需要在/etc/sysctl.conf添加
fs.file-max=102400
保存退出后使用sysctl -p 命令使其生效。
與file-max參數(shù)相對應(yīng)的還有file-nr,這個參數(shù)是只讀的,可以查看當(dāng)前文件描述符的使用情況。
直接修改內(nèi)核參數(shù),無須重啟系統(tǒng)。
sysctl -w fs.file-max 65536
或者
echo "65536" > /proc/sys/fs/file-max
兩者作用是相同的,前者改內(nèi)核參數(shù),后者直接作用于內(nèi)核參數(shù)在虛擬文件系統(tǒng)(procfs, psuedo file system)上對應(yīng)的文件而已。
可以用下面的命令查看新的限制
sysctl -a | grep fs.file-max
或者
cat /proc/sys/fs/file-max
修改內(nèi)核參數(shù)
/etc/sysctl.conf
echo "fs.file-max=65536" >> /etc/sysctl.conf
sysctl -p
查看當(dāng)前file handles使用情況:
sysctl -a | grep fs.file-nr
或者
cat /proc/sys/fs/file-nr
825 0 65536
另外一個命令:
lsof | wc -l
下面是摘自kernel document中關(guān)于file-max和file-nr參數(shù)的說明
file-max & file-nr:
The kernel allocates file handles dynamically, but as yet it doesn't free them again.
內(nèi)核可以動態(tài)的分配文件句柄,但到目前為止是不會釋放它們的
The value in file-max denotes the maximum number of file handles that the Linux kernel will allocate. When you get lots of error messages about running out of file handles, you might want to increase this limit.
file-max的值是linux內(nèi)核可以分配的最大文件句柄數(shù)。如果你看到了很多關(guān)于打開文件數(shù)已經(jīng)達(dá)到了最大值的錯誤信息,你可以試著增加該值的限制
Historically, the three values in file-nr denoted the number of allocated file handles, the number of allocated but unused file handles, and the maximum number of file handles. Linux 2.6 always reports 0 as the number of free file handles -- this is not an error, it just means that the number of allocated file handles exactly matches the number of used file handles.
在kernel 2.6之前的版本中,file-nr 中的值由三部分組成,分別為:1.已經(jīng)分配的文件句柄數(shù),2.已經(jīng)分配單沒有使用的文件句柄數(shù),3.最大文件句柄數(shù)。但在kernel 2.6版本中第二項的值總為0,這并不是一個錯誤,它實(shí)際上意味著已經(jīng)分配的文件句柄無一浪費(fèi)的都已經(jīng)被使用了
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
Text-to-speech function is limited to 100 characters
《動態(tài)網(wǎng)站設(shè)計十八般武藝 --ASP 篇》一文從第一期至今已和朋友們一起度過了大半個年頭,相信通過在這一段時間中的
學(xué)習(xí) 、實(shí)踐到再學(xué)習(xí)、再實(shí)踐,大家已經(jīng)能夠熟練運(yùn)用 ASP 的內(nèi)建對象、 ActiveX 組件去編寫一些基本的 ASP 應(yīng)用程序。從我收到的朋友們的來信中可以明顯的感覺到,大家的 ASP 功力正不斷地提升。最近很多朋友來信希望我寫一些 ASP 在現(xiàn)實(shí)運(yùn)用中的實(shí)例。因此,從本期開始我決定將《動態(tài)網(wǎng)站設(shè)計十八般武藝 --ASP 篇》的定位從介紹和學(xué)習(xí) ASP 基礎(chǔ)知識轉(zhuǎn)向到 ASP 實(shí)際運(yùn)行的探討和深化。應(yīng)朋友們的要求,在本期中我將給大家著重談一談“ADO 存取
數(shù)據(jù)庫 時如何分頁顯示”的問題。
什么是 ADO 存取數(shù)據(jù)庫時的分頁顯示?如果你使用過目前眾多網(wǎng)站上的電子公告板程序的話,那你應(yīng)該會知道電子公告板程序為了提高頁面的讀取速度,一般不會將所有的帖子全部在一頁中羅列出來,而是將其分成多頁顯示,每頁顯示一定數(shù)目的帖子數(shù),譬如 20 條。這就是數(shù)據(jù)庫查詢的分頁顯示,如果你還不明白,去看看 yahoo 等搜索引擎的查詢結(jié)果就會明白了。
那么究竟如何才能做到將數(shù)據(jù)庫的查詢結(jié)果分頁顯示呢?其實(shí)方法有很多,但主要有兩種:
一、將數(shù)據(jù)庫中所有符合查詢條件的記錄一次性的都讀入 recordset 中,存放在內(nèi)存中,然后通過 ADO Recordset 對象所提供的幾個專門支持分頁處理的屬性: PageSize( 頁大小 )、 PageCount( 頁數(shù)目 ) 以及 AbsolutePage( 絕對頁 ) 來管理分頁處理。
二、根據(jù)客戶的指示,每次分別從符合查詢條件的記錄中將規(guī)定數(shù)目的記錄數(shù)讀取出來并顯示。
兩者的主要差別在于前者是一次性將所有記錄都讀入內(nèi)存然后再根據(jù)指示來依次做判斷分析從而達(dá)到分頁顯示的效果,而后者是先根據(jù)指示做出判斷并將規(guī)定數(shù)目的符合查詢條件的記錄讀入內(nèi)存,從而直接達(dá)到分頁顯示的功能。
我們可以很明顯的感覺到,當(dāng)數(shù)據(jù)庫中的記錄數(shù)達(dá)到上萬或更多時,第一種方法的執(zhí)行效率將明顯低于第二種方法,因為當(dāng)每一個客戶查詢頁面時都要將所有符合條件的記錄存放在服務(wù)器內(nèi)存中,然后在進(jìn)行分頁等處理,如果同時有超過 100 個的客戶在線查詢,那么 ASP 應(yīng)用程序的執(zhí)行效率將大受影響。但是,當(dāng)服務(wù)器上數(shù)據(jù)庫的記錄數(shù)以及同時在線的人數(shù)并不是很多時,兩者在執(zhí)行效率上是相差無幾的,此時一般就采用第一種方法,因為第一種方法的 ASP 程序編寫相對第二種方法要簡單明了得多。
在這里作者就以我們常見的 ASP BBS 程序為例,來給大家分析一下如何在 BBS 程序里實(shí)現(xiàn)分頁顯示功能,由于我們一般使用的 BBS 程序的數(shù)據(jù)庫記錄數(shù)和同時訪問的人數(shù)都不會太多,所以以下程序?qū)嵗鞘褂玫南惹八榻B的第一種分頁顯示方法。
進(jìn)行 ADO 存取數(shù)據(jù)庫時的分頁顯示,其實(shí)就是對 Recordset 的記錄進(jìn)行操作。所以我們首先必須了解 Reordset 對象的屬性和方法:
BOF 屬性:目前指標(biāo)指到 RecordSet 的第一筆。
EOF 屬性:目前指標(biāo)指到 RecordSet 的最后一筆。
Move 方法:
移動 指標(biāo)到 RecordSet 中的某一條記錄。
AbsolutePage 屬性:設(shè)定當(dāng)前記錄的位置是位于哪一頁 AbsolutePosition 屬性:目前指標(biāo)在 RecordSet 中的位置。
PageCount 屬性:顯示 Recordset 對象包括多少“頁”的數(shù)據(jù)。
PageSize 屬性:顯示 Recordset 對象每一頁顯示的記錄數(shù)。
RecordCount 屬性:顯示 Recordset 對象記錄的總數(shù)。
下面讓我們來詳細(xì)認(rèn)識一下這些重要的屬性和方法
一、 BOF 與 EOF 屬性
通常我們在 ASP 程序中編寫代碼來檢驗 BOF 與 EOF 屬性,從而得知目前指標(biāo)所指向的 RecordSet 的位置,使用 BOF 與 EOF 屬性,可以得知一個 Recordset 對象是否包含有記錄或者得知移動記錄行是否已經(jīng)超出該 Recordset 對象的范圍。
如:
< % if not rs.eof then ... %>
< % if not (rs.bof and rs.eof) %>
若當(dāng)前記錄的位置是在一個 Recordset 對象第一行記錄之前時, BOF 屬性返回 true,反之則返回 false。
若當(dāng)前記錄的位置是在一個 Recordset 對象最后一行記錄之后時, EOF 屬性返回 true,反之則返回 false。
BOF 與 EOF 都為 False:表示指標(biāo)位于 RecordSet 的當(dāng)中。
BOF 為 True:目前指標(biāo)指到 RecordSet 的第一筆記錄。 EOF 為 True:目前指標(biāo)指到 RecordSet 的最后一筆記錄。
BOF 與 EOF 都為 True:在 RecordSet 里沒有任何記錄。
二、 Move 方法
您可以用 Move 方法移動指標(biāo)到 RecordSet 中的某一筆記錄,語法如下:
rs.Move NumRecords,Start
這里的“rs”為一個對象變量,表示一個想要移動當(dāng)當(dāng)前記錄位置的 Recordset 對象;“NumRecords”是一個正負(fù)數(shù)運(yùn)算式,設(shè)定當(dāng)前記錄位置的移動數(shù)目;“start”是一個可選的項目,用來指定記錄起始的標(biāo)簽。
所有的 Recordset 對象都支持 Move 方法,如果 NumRecords 參數(shù)大于零,當(dāng)前記錄位置向末尾的方向移動;如果其小于零,則當(dāng)前記錄位置向開頭的方向移動;如果一個空的 Recordset 對象調(diào)用 Move 方法,將會產(chǎn)生一個錯誤。
MoveFirst 方法:將當(dāng)前記錄位置移至第一筆記錄。
MoveLast 方法:將當(dāng)前記錄位置移至最后一筆記錄。
MoveNext 方法:將當(dāng)前記錄位置移至下一筆記錄。 MovePrevious 方法:將當(dāng)前記錄位置移至上一筆記錄。
Move [n] 方法:移動指標(biāo)到第 n 筆記錄, n 由 0 算起。
三、 AbsolutePage 屬性
AbsolutePage 屬性設(shè)定當(dāng)前記錄的位置是位于哪一頁的頁數(shù)編號;使用 PageSize 屬性將 Recordset 對象分割為邏輯上的頁數(shù),每一頁的記錄數(shù)為 PageSize( 除了最后一頁可能會有少于 PageSize 的記錄數(shù) )。這里必須注意并不是所有的數(shù)據(jù)提供者都支持此項屬性,因此使用時要小心。
與 AbsolutePosition 屬性相同, AbsolutePage 屬性是以 1 為起始的,若當(dāng)前記錄為 Recordset 的第一行記錄, AbsolutePage 為 1。可以設(shè)定 AbsolutePage 屬性,以移動到一個指定頁的第一行記錄位置。
四、 AbsolutePosition 屬性
若您需要確定目前指標(biāo)在 RecordSet 中的位置,您可以用 AbsolutePosition 屬性。
AbsolutePosition 屬性的數(shù)值為目前指標(biāo)相對於第一筆的位置,由 1 算起,即第一筆的 AbsolutePosition 為 1。
注意 , 在存取 RecordSet 時,無法保證 RecordSet 每次都以同樣的順序出現(xiàn)。
若要啟用 AbsolutePosition,必須先設(shè)定為使用用戶端 cursor( 指針 ), asp 碼如下:
rs2.CursorLocation = 3
五、 PageCount 屬性
使用 PageCount 屬性,決定 Recordset 對象包括多少“頁”的數(shù)據(jù)。這里的“頁”是數(shù)據(jù)記錄的集合,大小等于 PageSize 屬性的設(shè)定,即使最后一頁的記錄數(shù)比 PageSize 的值少,最后一頁也算是 PageCount 的一頁。必須注意也并不是所有的數(shù)據(jù)提供者都支持此項屬性。
六、 PageSize 屬性
PageSize 屬性是決定 ADO 存取數(shù)據(jù)庫時如何分頁顯示的關(guān)鍵,使用它就可以決定多少記錄組成一個邏輯上的“一頁”。設(shè)定并建立一個頁的大小,從而允許使用 AbsolutePage 屬性移到其它邏輯頁的第一條記錄。 PageSize 屬性能隨時被設(shè)定。
七、 RecordCount 屬性
這也是一個非常常用和重要的屬性,我們常用 RecordCount 屬性來找出一個 Recordset 對象包括多少條記錄。如: < % totle=RS.RecordCount %>
在了解了 Recordset 對象的以上屬性和方法后,我們來考慮一下,如何運(yùn)用它們來達(dá)到我們分頁顯示的目的。首先,我們可以為 PageSize 屬性設(shè)置一個值,從而指定從記錄組中取出的構(gòu)成一個頁的行數(shù);然后通過 RecordCount 屬性來確定記錄的總數(shù);再用記錄總數(shù)除以 PageSize 就可得到所顯示的頁面總數(shù);最后通過 AbsolutePage 屬性就能完成對指定頁的訪問。好象很并不復(fù)雜呀,下面讓我們來看看程序該如何實(shí)現(xiàn)呢?{上海治療陽痿醫(yī)院}
我們建立這樣一個簡單的 BBS 應(yīng)用程序,它的數(shù)據(jù)庫中分別有以下五個字段:“ID”,每個帖子的自動編號;“subject”,每個帖子的主題;“name”,加帖用戶的姓名; “email”,用戶的電子郵件地址;“postdate”,加帖的時間。數(shù)據(jù)庫的 DSN 為“bbs”。我們將顯示帖子分頁的所有步驟放在一個名為“ShowList()”的過程中,方便調(diào)用。程序如下:
\'----BBS 顯示帖子分頁----
< % Sub ShowList() %>
< %
PgSz=20 \'設(shè)定開關(guān),指定每一頁所顯示的帖子數(shù)目,默認(rèn)為20帖一頁
Set Conn = Server.CreateObject("ADODB.Connection")
Set RS = Server.CreateObject("ADODB.RecordSet")
sql = "SELECT * FROM message order by ID DESC"
\'查詢所有帖子,并按帖子的ID倒序排列
Conn.Open "bbs"
RS.open sql,Conn,1,1
If RS.RecordCount=0 then
response.write "< P>< center>對不起,數(shù)據(jù)庫中沒有相關(guān)信息!< /center>< /P>"
else
RS.PageSize = Cint(PgSz) \'設(shè)定PageSize屬性的值
Total=INT(RS.recordcount / PgSz * -1)*-1 \'計算可顯示頁面的總數(shù)
PageNo=Request("pageno")
if PageNo="" Then
PageNo = 1
else
PageNo=PageNo+1
PageNo=PageNo-1
end if
ScrollAction = Request("ScrollAction")
if ScrollAction = " 上一頁 " Then
PageNo=PageNo-1
end if
if ScrollAction = " 下一頁 " Then
PageNo=PageNo+1
end if
if PageNo < 1 Then
PageNo = 1
end if
n=1
RS.AbsolutePage = PageNo
Response.Write "< CENTER>"
position=RS.PageSize*PageNo
pagebegin=position-RS.PageSize+1
if position < RS.RecordCount then
pagend=position
else
pagend= RS.RecordCount
end if
Response.Write "< P>< font color=\'Navy\'>< B>數(shù)據(jù)庫查詢結(jié)果:< /B>"
Response.Write "(共有"&RS.RecordCount &"條符合條件的信息,顯示"&pagebegin&"-"&pagend&")< /font>< /p>"
Response.Write "< TABLE WIDTH=600 BORDER=1 CELLPADDING=4 CELLSPACING=0 BGCOLOR=#FFFFFF>"
Response.Write "< TR BGCOLOR=#5FB5E2>< FONT SIZE=2>< TD>< B>主題< /B>< /TD>< TD>< B>用戶< /B>< /TD>< TD>< B>Email< /B>< /TD>< TD>< B>發(fā)布日期< /B>< /TD>< /FONT>< TR BGCOLOR=#FFFFFF>"
Do while not (RS is nothing)
RowCount = RS.PageSize
Do While Not RS.EOF and rowcount >0
If n=1 then
Response.Write "< TR BGCOLOR=#FFFFFF>"
ELSE
Response.Write "< TR BGCOLOR=#EEEEEE>"
End If
n=1-n %>
< TD>< span style="font-size:9pt">< A href=\'view.asp?key=< % =RS("ID")%>\'>< % =RS("subject")%>< /A>< /span>< /td>
< TD>< span style="font-size:9pt">< % =RS("name")%>< /A>< /span>< /td>
< TD>< span style="font-size:9pt">< a href="mailto:< % =RS("email")%>">< % =RS("email")%>< /a>< /span>< /TD>
< TD>< span style="font-size:9pt">< % =RS("postdate")%>< /span>< /td>
< /TR>
< %
RowCount = RowCount - 1
RS.MoveNext
Loop
set RS = RS.NextRecordSet
Loop
Conn.Close
set rs = nothing
set Conn = nothing
%>
< /TABLE>
< FORM METHOD=GET ACTION="list.asp">
< INPUT TYPE="HIDDEN" NAME="pageno" VALUE="< % =PageNo %>">
< %
if PageNo >1 Then
response.write "< INPUT TYPE=SUBMIT NAME=\'ScrollAction\' VALUE=\' 上一頁 \'>"
end if
if RowCount = 0 and PageNo < >Total then
response.write "< INPUT TYPE=SUBMIT NAME=\'ScrollAction\' VALUE=\' 下一頁 \'>"
end if
response.write "< /FORM>"
End if
%>
< % End Sub %>
相信大家都應(yīng)該能完全讀懂上面的程序,因此作者就不在此詳細(xì)解釋了。值得注意的是在這段程序中運(yùn)用了一個小技巧
< INPUT TYPE="HIDDEN" NAME="pageno" VALUE="< % =PageNo %>">
,這是用來在每次調(diào)用該 ASP 文件時傳遞數(shù)據(jù)的“暗道”,由于我們需要在每次調(diào)用程序時傳遞代表當(dāng)前頁碼的參數(shù),可能大家會想到使用 session,但是從節(jié)省系統(tǒng)資源和通用性來講,用這樣一個隱藏的 form 來傳遞數(shù)據(jù)將會達(dá)到更好的效果。
好了,又到了說再見的時候了,如果你沒完全看懂本篇中所列的程序,那你必須加把油,看一看 VbScript 的語法;
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
Text-to-speech function is limited to 100 characters
這個bug出現(xiàn)在一年前,當(dāng)時自己大學(xué)還沒畢業(yè),剛剛進(jìn)入一家公司實(shí)習(xí)。那個時候還沒有用seajs或者requirejs那樣的模塊化管理的庫,也沒有用一個自執(zhí)行的函數(shù)將要執(zhí)行的代碼包裹起來,于是bug就在這樣的一個場景下誕生了。當(dāng)時自己定位了比較久,也不知道status是window下的一個屬性,所以請了高手幫忙定位,高手也是定位了半天才定位出來,只是湊巧將status換了一個名字就正常了,后來我問高手原因,他當(dāng)時也答不出來,后來就一直沒管它了,也忘記了。就在前幾天,群里有人在討論一些bug以及要注意的一些坑,我突然想起了一年前自己遇到過的坑,于是提了出來,在各位高手的討論下終于搞懂了這個bug出現(xiàn)的原因以及原理,于是記錄下,方便那些跟我一樣做開發(fā)的同學(xué)能夠繞過這些坑,少走彎路。
1.場景再現(xiàn)(為了方便最簡化代碼,當(dāng)時的情景不像下面這么直白的提示錯誤):
咦,為什么這里status是一個數(shù)組,為什么會提示它沒有push函數(shù)呢,這到底是為什么呢?這個bug對于當(dāng)時初出茅廬的我來說簡直就是一個大挑戰(zhàn),那個時候?qū)φ{(diào)試還不熟,看到bug那個小心臟頓時就有點(diǎn)受不了了,緊張啊,抓狂啊隨之而來。因為當(dāng)時代碼量比較多,所以當(dāng)時不能一下子定位到這里的問題。
2.討論
我們看到就因為變量名不同,卻一個出錯一個正常,難道不能將一個數(shù)組賦值給status嗎?
我們看到將一個數(shù)組賦值給status是完全沒有問題的,它是數(shù)組類型。既然是數(shù)組為什么就沒有push方法呢?這個時候我們不防打印下status的類型
我們看到我們將一個數(shù)組賦值給status,按理說應(yīng)該是object類型,可是這里卻是string類型,string類型沒有push方法,這時我們對于為什么報錯就沒有那么疑惑了。按這樣理解的話,就是在給status賦值時確實(shí)是將一個數(shù)組賦給了它,但是就是在讀取status時瀏覽器強(qiáng)制將status轉(zhuǎn)化成了字符串。我們不防在chrome控制臺看看。
看來我們的猜測是對的,賦值成功,在取值的時候?qū)tatus強(qiáng)制轉(zhuǎn)化為了字符串,那要是將一個對象賦值給status在讀取status的時候是不是也會將status轉(zhuǎn)化為json格式的字符串呢?
我們看到,瀏覽器并沒有按我們的預(yù)期將它轉(zhuǎn)化為一個json格式的字符串,而是轉(zhuǎn)化為[object Object]這樣的東東,這不是我們經(jīng)常用來判斷變量的類型嗎?一般我們會調(diào)用Object.prototype.toString.call(變量)來查看變量類型,因為使用typeof太不靠譜。于是我們猜到在將status轉(zhuǎn)化為字符串的時候是調(diào)用了toString方法。
難道status只能是字符串嗎?想想status當(dāng)初設(shè)計出來的初衷,它就是為了臨時在狀態(tài)欄展示一些用戶信息,所以必須是字符串。這樣理解的話就順理成章了。
所以我們看到使用status來定義變量是不可行的,除非定義的status是string類型,但是有的人就說,經(jīng)常用status,沒啥問題啊。
看,用得挺好的,妥妥的啊。
我們再來看另外一種情況。
xx,報錯了,咋回事?在項目中,由于我們的疏忽,有時候定義的變量忘記寫var關(guān)鍵字都是時常有的事,在一個代碼量很龐大的應(yīng)用中,定位這樣的一個bug肯定需要花費(fèi)不少時間,而且很容易讓人抓狂。
上面那種情況將一個數(shù)組賦值給status并調(diào)用push方法為啥不出錯,這里就涉及到j(luò)avascript變量作用域的問題了,因為一個自執(zhí)行函數(shù)就是一個作用域,系統(tǒng)在查找這個變量時是先在這個作用域內(nèi)進(jìn)行查找,找不到就往上一層作用域中查找,直到作用域的最前端,沒有找到就報錯提示變量is not defined。這里因為在當(dāng)前作用域中申明了變量status,所以不會去window環(huán)境下去查找status變量,所以是ok的,但是下面這種情況因為沒有使用var進(jìn)行變量的申明,所以status就會成為window下的變量,而status又是window下的一個固有屬性,取值的時候只能是string類型,從而沒有push方法,最終報錯。
所以,為了不給自己制造那么多麻煩,在定義變量時應(yīng)該盡量避免使用javascript中的關(guān)鍵字、保留字和window下的固有屬性進(jìn)行命名,這些都是坑,實(shí)際項目中應(yīng)該多注意避免。
從以上分析中,我們看到全局的status可以設(shè)置,但是讀取的時候卻調(diào)用了toSting方法返回了字符串,這里我們可以利用es5提供的Object.defineProperty來模擬一下這種行為。代碼如下:
var a = {};
Object.defineProperty(a, 'm', (function () {
var _a = 'xx';
return {
get : function () {
return _a.toString();
},
set : function (v) {
_a = v;
}
};
})());
利用Object.defineProperty方法,可以對一個變量或者屬性進(jìn)行監(jiān)控,當(dāng)直接賦值給變量的時候就會調(diào)用set方法,當(dāng)直接讀取變量的時候就會將調(diào)用tostring方法將變量轉(zhuǎn)化為字符串。
我們看到我們模擬的行為和status默認(rèn)的行為一模一樣。
一年前遇到的bug今天才豁然開朗,這讓我意識到針對任何一個小的bug都不應(yīng)該放過,而要報著打破沙鍋問到底的態(tài)度去探究,這樣才可以看到別樣的風(fēng)景以及讓自己更加專業(yè)。
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
Text-to-speech function is limited to 100 characters
總體是利用
TestNG 里面的IRetryAnalyzer、TestListenerAdapter接口來實(shí)現(xiàn)相關(guān)問題
1、定義一個自己的retryanalyzer
import org.testng.ITestResult;
import org.testng.util.RetryAnalyzerCount;
//這里集成自抽象類RetryAnalyzerCount,該抽象類實(shí)現(xiàn)了IRetryAnalyzer
public class TestRetryAnalyzer extends RetryAnalyzerCount{
public TestRetryAnalyzer(){
setCount(1);
}
@Override
public boolean retryMethod(ITestResult arg0) {
// TODO Auto-generated method stub
return true;
}
}
2、定義自己的監(jiān)聽器,集成自TestListenerAdapter
import
java .util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.testng.IResultMap;
import org.testng.ITestContext;
import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.TestListenerAdapter;
import org.testng.ITestNGMethod;
import org.testng.collections.Lists;
import org.testng.collections.Objects;
public class RetryTestListener extends TestListenerAdapter {
private List<ITestNGMethod> m_allTestMethods =
Collections.synchronizedList(Lists.<ITestNGMethod>newArrayList());
private List<ITestResult> m_passedTests = Collections.synchronizedList(Lists.<ITestResult>newArrayList());
private List<ITestResult> m_failedTests = Collections.synchronizedList(Lists.<ITestResult>newArrayList());
private List<ITestResult> m_skippedTests = Collections.synchronizedList(Lists.<ITestResult>newArrayList());
private List<ITestResult> m_failedButWSPerTests = Collections.synchronizedList(Lists.<ITestResult>newArrayList());
private List<ITestContext> m_testContexts= Collections.synchronizedList(new ArrayList<ITestContext>());
private List<ITestResult> m_failedConfs= Collections.synchronizedList(Lists.<ITestResult>newArrayList());
private List<ITestResult> m_skippedConfs= Collections.synchronizedList(Lists.<ITestResult>newArrayList());
private List<ITestResult> m_passedConfs= Collections.synchronizedList(Lists.<ITestResult>newArrayList());
public synchronized void onTestFailure(ITestResult arg0) {
m_allTestMethods.add(arg0.getMethod());
m_failedTests.add(arg0);
}
@Override
public void onFinish(ITestContext context) {
for(int i=0;i<context.getAllTestMethods().length;i++){
System.out.println("~~~~~~~~~~"+context.getAllTestMethods()[i].getCurrentInvocationCount());
if(context.getAllTestMethods()[i].getCurrentInvocationCount()==2){
System.out.println("~~~~~~~~~~~~~~~~~"+context.getAllTestMethods()[i].getParameterInvocationCount());
System.out.println(context.getAllTestMethods()[i].ignoreMissingDependencies());
if
(context.getFailedTests().getResults(context.getAllTestMethods()[i]).size()
== 2 ||
context.getPassedTests().getResults(context.getAllTestMethods()[i]).size()
== 1){
context.getFailedTests().removeResult(context.getAllTestMethods()[i]);
}
}
}
}
...
}
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
Text-to-speech function is limited to 100 characters
1.LR12是11.52的完成版本,確實(shí)覺得整體舒服多了,用起來不是那么別扭了,有些菜單的優(yōu)化還是不錯的
2.對于win8.1和ie11支持確實(shí)很好,采用了新的證書策略,效果不錯
3.trueclient的錄制模式還是和以前差不多
4.對于
手機(jī) 端的模擬測試多了不少的平臺,包括nexus7之類的平臺也有了
5.錄制支持chrome了,但是我用最新的33還是出現(xiàn)了無響應(yīng)的問題,不過奇怪的是UFT12對chrome33這樣的最新版本支持的很好。
6.提供了直接的端口代理錄制模式,用起來很方便直接修改應(yīng)用的代理地址到LR配置的地址就行了,但是用IE11走代理模式出現(xiàn)了請求錄制成功,但返回的頁面沒有出現(xiàn)的情況,就是請求出去了,但是沒返回到瀏覽器中的情況,實(shí)際就是還是沒法用啊。
7.runtime setting的這類跟蹤調(diào)試功能貌似增強(qiáng)了。
總結(jié):
如果你已經(jīng)習(xí)慣用lr11.52了,那么12還是非常值得升級的版本,確實(shí)很多地方人性了。
如果你還是傳統(tǒng)用戶,個人覺得11還是一個最合適的版本,至少用起來還是比12快不少。我的虛擬機(jī)是i7 930 2X2+4G內(nèi)存+raid0硬盤,應(yīng)該不算很差了。
如果某些特殊的東西實(shí)在LR11不支持,你可以試試LR12.
如果你還不知道怎么“
學(xué)習(xí) 版”的話,LR12的默認(rèn)50個用戶策略和可能一直免費(fèi)的License,會讓你少處理很多東西。
如果你是新學(xué)LR,個人還是建議你用老版本,因為LR12真沒啥學(xué)習(xí)資料。
如果你是老手,用LR12就和普通的一樣,道理明白了新版本真沒啥新意。
ps.貌似有個bug就是默認(rèn)裝完了第一次用Load generator的時候系統(tǒng)自動選的是localhost但是其實(shí)是沒有這個負(fù)載生成機(jī)的,需要自己去列表里面添加一個再選擇了才能跑負(fù)載。
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
Text-to-speech function is limited to 100 characters