JMeter (2) —— JMeter與WebDriver測試用戶登陸以CAS SSO為例(101 Tutorial)


JMeter (2) —— JMeter與WebDriver測試用戶登陸以CAS SSO為例(101 Tutorial)


主要內容

  • JMeter與WebDriver測試用戶登陸以CAS SSO為例

環境與參考

jvm版本: 1.8.0_65

jmeter版本: 2.13

firefox版本: 39.0.3

參考來源:

jmeter官方網站

Leverage your Load Testing using JMeter and Selenium WebDriver

jmeter-plugins.org:FirefoxDriverConfig

jmeter-plugins.org:WebDriverTutorial

jmeter-plugins.org:WebDriverSampler

Using Selenium with JMeter's WebDriver Sampler

准備

請參照JMeter (1) —— JMeter與WebDriver安裝與測試(101 Tutorial) 安裝好JMeter。

需要注意的是:

  • JMeter的版本
  • jar依賴沖突
  • firefox版本

待測試的CAS環境

架構

配置

請參照以下文章搭建配置好CAS單點登陸的本地環境。

測試

注意:我們這里只是以CAS單點登陸為應用場景進行測試,此測試可以推廣到其他的web應用的登陸場景,也可以擴展到更為豐富的流程或場景中。

准備

  1. 新建測試計划(TestPlan)

  2. 為測試計划添加線程組(TheadGroup)

  3. 依次添加

    • jp@gc - Firefox Driver Config (Thread Group -> Config Element)
    • jp@gc - WebDriver Sampler (Thread Group -> Sampler)
    • View Results Tree (Thread Group -> Listender)
    • View Results in Table (Thread Group -> Listender)

測試本地的CAS單點登陸環境

  1. 腳本

     try {
         
         var pkg = JavaImporter(org.openqa.selenium, org.openqa.selenium.support.ui)
         WDS.log.info('WDS Name:' + WDS.name)
         WDS.sampleResult.sampleStart()
         
         WDS.browser.navigate().to('https://app2.hoau.com:8423/cas2')
         WDS.log.info('Browser Title:' + WDS.browser.getTitle())
         WDS.log.info('Browser CurrentUrl:' + WDS.browser.getCurrentUrl())    
         WDS.log.info('Cookie:' + WDS.browser.manage().getCookies())   
         WDS.log.info('Request Header: ' + WDS.sampleResult.getRequestHeaders())
         
         var what = WDS.browser.findElement(pkg.By.id('username'))
         what.sendKeys(['test01'])
         var where = WDS.browser.findElement(pkg.By.id('password'))
         where.sendKeys(['psw01'])
         
      
         //   var button = WDS.browser.findElement(pkg.By.cssSelector('.btn-submit'))
         var button = WDS.browser.findElement(pkg.By.xpath("//input[@type='submit']"))
         button.click()
         
         
         var wait = new pkg.WebDriverWait(WDS.browser, 10)
         wait.until(pkg.ExpectedConditions.presenceOfElementLocated(pkg.By.xpath("//a[@title='Click here to log out']")))
         var results = WDS.browser.findElements(pkg.By.xpath("//a[@title='Click here to log out']"))
         WDS.log.info('Result: ' + results)
         
         if(results.empty) {
             WDS.sampleResult.successful = false
             WDS.sampleResult.responseMessage = 'There were no results returned'
         }
         
         var iter = results.iterator()
         var element = iter.next()
         WDS.log.info('User: ' + element.getText())
         
         if('test01' != element.getText()) {
             WDS.sampleResult.successful = false
             WDS.sampleResult.responseMessage = 'Login Failure'
         }
         
         WDS.sampleResult.sampleEnd()
     } catch(ex) {
         WDS.log.error(ex)
         WDS.sampleResult.successful = false
         WDS.sampleResult.responseMessage = 'There were no results returned'
         WDS.sampleResult.sampleEnd()
     }
    
  2. 運行

    • 查看“View Results in Table”

    • 查看“View Results Tree”

需要注意的是,諸如JMeter + WebDriver Plugin或Selenium Grid + Remote WebDriver抑或Sahi Web UI這些方式的測試,都是試圖模擬用戶從終端(瀏覽器)與服務器進行真實交互,以上這些方式長於流程、場景,而非服務端的壓力(當然也可用於服務端壓力測試之目的,這里強調的只是意圖),如果要對服務端進行壓力測試,我們可以有其他更為適合的方式。

測試cnblogs登陸

我們同樣可以cnblogs為目標系統,嘗試用JMeter來測試cnblogs的登陸。

  1. 腳本

     try {
         
         var pkg = JavaImporter(org.openqa.selenium, org.openqa.selenium.support.ui)
         WDS.log.info('WDS Name:' + WDS.name)
         WDS.sampleResult.sampleStart()
         
         WDS.browser.navigate().to('http://passport.cnblogs.com/user/signin')
         WDS.log.info('Browser Title:' + WDS.browser.getTitle())
         WDS.log.info('Browser CurrentUrl:' + WDS.browser.getCurrentUrl())    
         WDS.log.info('Cookie:' + WDS.browser.manage().getCookies())   
         WDS.log.info('Request Header: ' + WDS.sampleResult.getRequestHeaders())
         
         var what = WDS.browser.findElement(pkg.By.id('input1'))
         what.sendKeys(['weizhe_2008'])
         var where = WDS.browser.findElement(pkg.By.id('input2'))
         where.sendKeys(['********'])
         var button = WDS.browser.findElement(pkg.By.id('signin'))
         button.click()
         
         var wait = new pkg.WebDriverWait(WDS.browser, 1)
         // a href="http://home.cnblogs.com/u/richaaaard/"
         wait.until(pkg.ExpectedConditions.presenceOfElementLocated(pkg.By.xpath("//a[@href='http://www.cnblogs.com/richaaaard/']")))
         var results = WDS.browser.findElements(pkg.By.xpath("//a[@href='http://www.cnblogs.com/richaaaard/']"))
         WDS.log.info('Result: ' + results)
         
         if(results.empty) {
             WDS.sampleResult.successful = false
             WDS.sampleResult.responseMessage = 'There were no results returned'
         }
         
         WDS.sampleResult.sampleEnd()
     } catch(ex) {
         WDS.log.error(ex)
         WDS.sampleResult.successful = false
         WDS.sampleResult.responseMessage = 'There were no results returned'
         WDS.sampleResult.sampleEnd()
     }
    
  2. 運行

  3. 結果

問題

  • 由於此種測試模式下,我們會使用JMeter配置的Firefox Driver Config組件,同時使用WDS(Web Driver Sampler)Script在JMeter UI環境下測試目標應用,當Thread Group 的循環次數(Loop Count)或線程數(Number of Threads (user))的值大於1時,當前線程關聯的瀏覽器代理實例一直處於生命期,而單點登陸會保留用戶的登陸信息,無需反復輸入用戶名密碼,瀏覽器保持了這些信息,因此后面斷言會出現錯誤,腳本無法反復執行從而達到為“驗證用戶名密碼這個流程”進行壓力測試的目的。

    經研究,當前版本的JMeter及其使用的Selenium WebDriver Plugin除PhantomJS外,不支持動態修改Session Cookie,而網上多數文章介紹的相關Cookie的API,無法對瀏覽器Session Cookie進行操作。

      WDS.browser.manage().getCookies()
      WDS.browser.manage().deleteAllCookies()
    

    我們會使用HTTPs錄制的方式來解決壓力測試的問題。

擴展

為了解WDS 在JMeterUI下javascript腳本的能力,以及涉及到面問題相關的源碼。

  • WDS (JMeterPlugins-WebDriver.jar)

    com.googlecode.jmeter.plugins.webdriver.sampler.WebDriverSampler
    com.googlecode.jmeter.plugins.webdriver.sampler.WebDriverScriptable

      package com.googlecode.jmeter.plugins.webdriver.sampler;
    
      import org.apache.jmeter.samplers.SampleResult;
      import org.apache.log.Logger;
      import org.openqa.selenium.WebDriver;
    
      public final class WebDriverScriptable
      {
        private static final String[] EMPTY_ARGS = new String[0];
        private String name;
        private String parameters;
        private Logger log;
        private WebDriver browser;
        private SampleResult sampleResult;
    
        public void setName(String name)
        {
          this.name = name;
        }
    
        public String getName() {
          return this.name;
        }
    
        public void setParameters(String parameters) {
          this.parameters = parameters;
        }
    
        public String getParameters() {
          return this.parameters;
        }
    
        public String[] getArgs() {
          return this.parameters != null ? this.parameters.trim().replaceAll("\\s+", " ").split(" ") : EMPTY_ARGS;
        }
    
        public void setLog(Logger log) {
          this.log = log;
        }
    
        public Logger getLog() {
          return this.log;
        }
    
        public void setBrowser(WebDriver browser) {
          this.browser = browser;
        }
    
        public WebDriver getBrowser() {
          return this.browser;
        }
    
        public void setSampleResult(SampleResult sampleResult) {
          this.sampleResult = sampleResult;
        }
    
        public SampleResult getSampleResult() {
          return this.sampleResult;
        }
      }		
    
  • WDS.browser (WebDriver - selenium-api-2.47.0.jar)

    org.openqa.selenium.WebDriver
    org.openqa.selenium.Cookie

    package org.openqa.selenium;
    
    import java.net.URL;
    import java.util.List;
    import java.util.Set;
    import java.util.concurrent.TimeUnit;
    import org.openqa.selenium.logging.Logs;
    
    public abstract interface WebDriver extends SearchContext
    {
      public abstract void get(String paramString);
    
      public abstract String getCurrentUrl();
    
      public abstract String getTitle();
    
      public abstract List<WebElement> findElements(By paramBy);
    
      public abstract WebElement findElement(By paramBy);
    
      public abstract String getPageSource();
    
      public abstract void close();
    
      public abstract void quit();
    
      public abstract Set<String> getWindowHandles();
    
      public abstract String getWindowHandle();
    
      public abstract TargetLocator switchTo();
    
      public abstract Navigation navigate();
    
      public abstract Options manage();
    
      @Beta
      public static abstract interface Window
      {
        public abstract void setSize(Dimension paramDimension);
    
        public abstract void setPosition(Point paramPoint);
    
        public abstract Dimension getSize();
    
        public abstract Point getPosition();
    
        public abstract void maximize();
      }
    
      public static abstract interface ImeHandler
      {
        public abstract List<String> getAvailableEngines();
    
        public abstract String getActiveEngine();
    
        public abstract boolean isActivated();
    
        public abstract void deactivate();
    
        public abstract void activateEngine(String paramString);
      }
    
      public static abstract interface Navigation
      {
        public abstract void back();
    
        public abstract void forward();
    
        public abstract void to(String paramString);
    
        public abstract void to(URL paramURL);
    
        public abstract void refresh();
      }
    
      public static abstract interface TargetLocator
      {
        public abstract WebDriver frame(int paramInt);
    
        public abstract WebDriver frame(String paramString);
    
        public abstract WebDriver frame(WebElement paramWebElement);
    
        public abstract WebDriver parentFrame();
    
        public abstract WebDriver window(String paramString);
    
        public abstract WebDriver defaultContent();
    
        public abstract WebElement activeElement();
    
        public abstract Alert alert();
      }
    
      public static abstract interface Timeouts
      {
        public abstract Timeouts implicitlyWait(long paramLong, TimeUnit paramTimeUnit);
    
        public abstract Timeouts setScriptTimeout(long paramLong, TimeUnit paramTimeUnit);
    
        public abstract Timeouts pageLoadTimeout(long paramLong, TimeUnit paramTimeUnit);
      }
    
      public static abstract interface Options
      {
        public abstract void addCookie(Cookie paramCookie);
    
        public abstract void deleteCookieNamed(String paramString);
    
        public abstract void deleteCookie(Cookie paramCookie);
    
        public abstract void deleteAllCookies();
    
        public abstract Set<Cookie> getCookies();
    
        public abstract Cookie getCookieNamed(String paramString);
    
        public abstract WebDriver.Timeouts timeouts();
    
        public abstract WebDriver.ImeHandler ime();
    
        @Beta
        public abstract WebDriver.Window window();
    
        @Beta
        public abstract Logs logs();
      }
    }	
    

    以上要注意內部靜態類 Options里面提供的,對Cookie進行操作的API

結束


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM