qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          自己動手寫壓力測試

          信息如水 壓力如潮
            功能實現階段,我們對得要處理的信息分析得很細致,很透徹,所謂細如絲,透如水。然而,到了產品的階段,要處理的信息卻如同潮洪而至,原本的假設預想,通通被擊成了碎片。這時候產生的錯誤和問題,很難在開發機上重現。
            如果說用戶驗收測試是對功能實現的檢查,需要滴水不漏;壓力測試則是容量的考驗,迎接浪的洗禮。
            環肥燕瘦
            壓力測試的工具頗多,尤其是HP的LoadRunner甚至成為了行業標準。可是,在研究和考察的過程中,心里卻慢慢有了質疑,我是否非得用這些工具嗎? 一則,它們是商業軟件,價格不菲;二則,還是因為是商業軟件,功能太多,太龐大,很多東西我都不需要。為什么不自己做一個簡單實用的呢?
            在小趙研究Selenium時,我覺得用他用的語法很貼近業務語言,于是我提出一個問題,可以用于壓力測試嗎?他說不行,因為Selenium是要完全啟動瀏覽器。平時,看起來瘦小的瀏覽器,其實很耗資源,特別是與壓力測試的容量來比,瀏覽器是個不折不扣的大胖子。你可以試一下,在你的機器上同時開啟100個瀏覽窗口,會是個什么狀況。
            苗條美人 HttpClient
            否定了Selenium之后,很快就找到了我的目標HttpClient (其實還有個前生WebClient,后面有敘)。從名稱,我們就可以知道,它已經定位到很低Http層,這一層是效率與易用的一個最佳平衡點。但是,它是.Net 4.5下的部件,在.Net 4.0必須用NuGet來下載。
            查看了很多資料以后,我可以確信,HttpClient正是我想要的。她還有一個很大的特色,完全只提供異步接口。這實際上是另一種大瘦身,耗用資源上的瘦身,HttpClient正式我要的窈窕淑女。
            前生:WebClient
          var values = new NameValueCollection();
          foreach (var key_value in ui.FormData)
          {
          values.Add(key_value.Key, key_value.Value);
          }
          var client = new WebClient();
          client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
          Console.WriteLine(string.Concat(base_site + ui.Path, ui.Method.ToString().ToLower(), values));
          byte[] result = client.UploadValues(base_site + ui.Path, ui.Method.ToString().ToLower(), values);
          string ResultAuthTicket = Encoding.UTF8.GetString(result);
          Console.WriteLine(client.BaseAddress);
          Console.WriteLine(client.ResponseHeaders.ToString());
          Console.WriteLine(ResultAuthTicket);
            HttpClient的Async方法,注意最后的Wait()有把異步轉化為了同步
          var form_data=new Dictionary<string, string>();
          form_data.Add("system_account","test1@skight.com");
          form_data.Add("system_password","123456");
          var values = new NameValueCollection();
          foreach (var key_value in form_data)
          {
          values.Add(key_value.Key, key_value.Value);
          }
          var client = new HttpClient();
          client.GetStringAsync("http://esr20syst.skight.com/District/03/UserLogin.do")
          .ContinueWith(
          t =>
          {
          Console.WriteLine("Time {0}", DateTime.Now);
          Console.WriteLine(t.Result);
          })
          .Wait();


           Sync 還是Async 這,是一個問題
            .Net 4,5 出來之后,一直沒有對它的新功能和特性太在意。只是公司升級使用VS2012,除了灰不溜秋的界面,而所謂的性能提高(其實,是VS2010太次)之外,也沒有特別感覺。
            然而,這次在查看HttpClient資料時,卻意外發現了.Net 4.5 語法級別的一個亮點: Asyn和Await。這讓異步編程更簡便,更漂亮。看來,今后異步編程是一個大潮流,微軟也不惜余力。
            新語法應用之后的效果,似乎和平時的同步編碼沒有太大區別,除了不時冒出來的Await和Async
          var form_data=new Dictionary<string, string>();
          form_data.Add("system_account","test1@skight.com");
          form_data.Add("system_password","123456");
          foreach (var key_value in form_data)
          {
          values.Add(key_value.Key, key_value.Value);
          }
          var httpClient = new HttpClient();
          var content= await httpClient.GetStringAsync("http://esr20syst.skight.com/District/03/UserLogin.do");
          Console.WriteLine(t.Result);
            異步性能的福利是不可隨小覷的。之前,有Node.js構建的的Web服務比Apache快很多(http://zgadzaj.com/benchmarking-nodejs-basic-performance-tests-against-apache-php)就是得益于Javascript天生的函數回調方式支持的異步運行。現在有.Net對Async的友好支持,以及大量組件基于異步方式的重寫。據說,微軟推薦,凡是運行時間超過20毫秒的功能,就要用異步方式來寫。HttpClient就是一個例子,它的前身WebClient就不具異步調用,而HttpClient干脆就不提供同步接口。
            平行宇宙 Parallel
            其實,無論是的Async還是Parallel,都是語法糖,可是作為辛苦的開發者,我們好的就是這一口。
            Async讓我們發出網絡請不必再等待,Parallel讓我們很容易的持續發出平行請求,這就是一個完全的壓力測試模型了。我這里簡單設置了一個100 * 10 個請求。沒有具體計算,共發出多少個請求,我只知道,多得已經足夠讓我的系統重現產品機上的問題了。
          Parallel.For(1, 1000, i =>
          Parallel.For(1, 5, case_number =>
          LoginScenario(case_number)
          .run_by(runner)
          ));
            附:我的業務語法糖DSL
            這里是我對系統頁面操作的定義代碼,用語法糖DSL的方式實現,一定程度上實現了需求即代碼即文檔的要求吧。這部分代碼不能直接運行,因為它使用了我自己的Web框架,從而可以用強類型自動生成URL。這里提供出來只是作參考,作為示例的一部分。
          private static Scenario LoginScenario(int case_number)
          {
          return
          UI.context(Keys.Context.District.with_value(DistrictIdentifier.of("03")))
          .to<UserLoginGet>()
          .then(
          UI.input(SystemPayloadKeys.Account.with_value(string.Format("test{0}@skight.com", case_number)))
          .and_input(SystemPayloadKeys.Password.with_value("123456"))
          .to<UserLoginPost>());
          }

          posted on 2014-01-13 11:02 順其自然EVO 閱讀(292) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          <2014年1月>
          2930311234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 武宣县| 霍城县| 仲巴县| 望都县| 平泉县| 上饶市| 东宁县| 新丰县| 绵竹市| 巴马| 百色市| 随州市| 长岛县| 太仆寺旗| 望江县| 东安县| 天祝| 云霄县| 达日县| 元阳县| 大方县| 信阳市| 陆良县| 临沧市| 确山县| 长乐市| 临城县| 榕江县| 喀喇沁旗| 乌苏市| 海安县| 长顺县| 哈尔滨市| 瓮安县| 沙田区| 黑龙江省| 仁怀市| 航空| 南京市| 闸北区| 兴国县|