zoukankan      html  css  js  c++  java
  • Selenium 2 & WebDriver &多线程 并发

         我用的是Selenium2,至于它的背景和历史就不赘述了。Selenium2也叫WebDriver。下面讲个例子,用WebDriver+java来写个自动化测试的程序。(如果能用firefox去测试的话,我就直接用Selenium IDE录脚本了。。。)有个前提:就是我们只用IE浏览器(WebDriver支持多种浏览器)。需求:打开网易163邮箱,并且登录,然后打开收件箱;以上哪一步异常就截屏。这是我的程序要做的自动化测试的功能。

         首先需要去官网下载WebDriver和IE的驱动IEDriverServer.exe(根据你的系统,64位系统必须用64位的驱动,32位运行不了;32位的系统同理)

         官网下载地址:http://docs.seleniumhq.org/download/

         下面是下载位置的截图:

        

          由于我用到了多线程,所以我将代码放在了一个线程里面,多线程的事情后面再说,先看打开一个浏览器完成需求功能的代码。(单元测试工具我这里用的是testNG)

      1 import java.io.File;
      2 import java.net.URL;
      3 import java.text.SimpleDateFormat;
      4 import java.util.Date;
      5 
      6 import org.openqa.selenium.By;
      7 import org.openqa.selenium.OutputType;
      8 import org.openqa.selenium.Platform;
      9 import org.openqa.selenium.TakesScreenshot;
     10 import org.openqa.selenium.WebDriver;
     11 import org.openqa.selenium.WebElement;
     12 import org.openqa.selenium.ie.InternetExplorerDriver;
     13 import org.openqa.selenium.remote.DesiredCapabilities;
     14 import org.openqa.selenium.remote.RemoteWebDriver;
     15 import org.openqa.selenium.support.ui.ExpectedCondition;
     16 import org.openqa.selenium.support.ui.WebDriverWait;
     17 import org.testng.annotations.Test;
     18 
     19 
     20 
     21 public class TestLogin_testNG implements Runnable{
     22     public static final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSS");
     23 
     24     @Test
     25     public void run() {
     26         System.out.println(Thread.currentThread().getId()+"-----------------------"+sf.format(new Date()));//打印线程启动时间
     27         
     28         /*
     29          * 当采用 InterenetExplorerDriver时,可能会遇到一个安全问题提示:"Protected Mode must be
     30          * set to the same value (enabled or disabled) for all
     31          * zones"。想要解决这一问题,需要设置特定的功能
     32          */
     33         DesiredCapabilities capability = DesiredCapabilities.internetExplorer();
     34         capability.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS,true);
     35         
     36         //最好设置,用来匹配node中要使用的浏览器
     37         capability.setBrowserName("internet explorer");
     38         capability.setVersion("9");
     39         capability.setPlatform(Platform.WINDOWS);
     40         
     41         WebDriver driver = null;
     42         
     43         //设置本地驱动,如果你实例化Driver的时候是"WebDriver driver = new InternetExplorerDriver(capability)"这种方式,就必须设置
     44         System.setProperty("webdriver.ie.driver","D:\IEDriverServer.exe");
     45         
     46         try{
     47             driver = new InternetExplorerDriver(capability);//本地测试,非远程方式
     48 //            driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"),capability);//远程方式,想用多线程需要这么写
     49             System.out.println(Thread.currentThread().getId()+"访问163邮箱网页开始时间:"+sf.format(new Date()));
     50             
     51             driver.get("http://mail.163.com/");//打开网页
     52             
     53             try {
     54                 //等待页面打开,超时设置3秒
     55                 WebElement username = new WebDriverWait(driver, 3).until(new ExpectedCondition<WebElement>() {
     56                     public WebElement apply(WebDriver d) {
     57                         return d.findElement(By.id("idInput"));
     58                     }
     59                 });
     60                 if(null==username){
     61                     System.out.println(Thread.currentThread().getId()+" Visit http://mail.163.com/ Timeout !!!");
     62                     this.CaptureScreenshot(Thread.currentThread().getId()+"visit", driver);
     63                     driver.quit();
     64                     Thread.currentThread().interrupt();
     65                 }else{
     66                     System.out.println(Thread.currentThread().getId()+"访问163邮箱网页结束时间:"+sf.format(new Date()));
     67                     
     68                     username.clear();//清除username的value
     69                     username.sendKeys("testDemobyxy");//设置username的value
     70                     
     71                     WebElement pwd = driver.findElement(By.id("pwdInput"));
     72                     pwd.clear();
     73                     pwd.sendKeys("testDemobyxy123");
     74                     
     75                     WebElement submit = driver.findElement(By.id("loginBtn"));
     76                     
     77                     System.out.println(Thread.currentThread().getId()+"登录开始时间:"+sf.format(new Date()));
     78                     submit.click();//提交
     79                     
     80                     try {
     81                         //等待登录成功,超时设置3秒
     82                         WebElement inbox = new WebDriverWait(driver, 3).until(new ExpectedCondition<WebElement>() {
     83                             public WebElement apply(WebDriver d) {
     84                                 return  d.findElement(By.id("_mail_component_2_2"));
     85                             }
     86                         });
     87                         if(null==inbox){
     88                             System.out.println(Thread.currentThread().getId()+" Loign email Timeout !!!");
     89                             this.CaptureScreenshot(Thread.currentThread().getId()+"login", driver);
     90                             driver.quit();
     91                             Thread.currentThread().interrupt();
     92                         }else{
     93                             System.out.println(Thread.currentThread().getId()+"登录成功时间:"+sf.format(new Date()));
     94                             
     95                             System.out.println(Thread.currentThread().getId()+"点击收件箱时间:"+sf.format(new Date()));
     96                             inbox.click();
     97                             
     98                             try {
     99                                 //等待打开收件箱页面,超时设置3秒
    100                                 Boolean flag = new WebDriverWait(driver, 3).until(new ExpectedCondition<Boolean>() {
    101                                     public Boolean apply(WebDriver d) {
    102                                         return  d.findElement(By.id("_mail_button_4_114")) != null;
    103                                     }
    104                                 });
    105                                 if(!flag){
    106                                     System.out.println(Thread.currentThread().getId()+" Open inBox page Timeout !!!");
    107                                     this.CaptureScreenshot(Thread.currentThread().getId()+"openInboxPage", driver);
    108                                     driver.quit();
    109                                     Thread.currentThread().interrupt();
    110                                 }else{
    111                                     System.out.println(Thread.currentThread().getId()+"打开收件箱时间:"+sf.format(new Date()));
    112                                     driver.quit();
    113                                 }
    114                             } catch (Exception e) {
    115                                 System.out.println(Thread.currentThread().getId()+" Open inBox page Error !!!");
    116                                 e.printStackTrace();
    117                                 this.CaptureScreenshot(Thread.currentThread().getId()+"openInboxPage", driver);
    118                                 driver.quit();
    119                                 Thread.currentThread().interrupt();
    120                             }
    121                         }
    122                     } catch (Exception e) {
    123                         System.out.println(Thread.currentThread().getId()+" Loign email Error !!!");
    124                         e.printStackTrace();
    125                         this.CaptureScreenshot(Thread.currentThread().getId()+"login", driver);
    126                         driver.quit();
    127                         Thread.currentThread().interrupt();
    128                     }
    129                 }
    130             } catch (Exception e) {
    131                 System.out.println(Thread.currentThread().getId()+" Visit http://mail.163.com/ Error !!!");
    132                 e.printStackTrace();
    133                 this.CaptureScreenshot(Thread.currentThread().getId()+"visit", driver);
    134                 driver.quit();
    135                 Thread.currentThread().interrupt();
    136             }
    137         }catch (Exception e) {
    138             e.printStackTrace();
    139             this.CaptureScreenshot(Thread.currentThread().getId()+"visit", driver);
    140             driver.quit();
    141         }finally{
    142             if(null!=driver){
    143                 driver.quit();
    144             }
    145         }
    146     }
    147 
    148     /**
    149      * 截屏方法
    150      * @param fileName
    151      * @param driver
    152      */
    153     public void CaptureScreenshot(String fileName, WebDriver driver) {
    154         String dirName = "d:/screenshot";
    155         if (!(new File(dirName).isDirectory())) {
    156             new File(dirName).mkdir();
    157         }
    158         SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmss");
    159         String time = sdf.format(new Date());
    160         TakesScreenshot tsDriver = (TakesScreenshot) driver;
    161         File image = new File(dirName + File.separator + time + "_" + fileName==null?"":fileName + ".png");
    162         tsDriver.getScreenshotAs(OutputType.FILE).renameTo(image);
    163     }
    164 }

      代码比较简单,下面主要说下多线程的问题。可以看到我上面的代码是一个线程。由于需求上的要求要有一定数量的并发,所以我写了一个测试类,里面只有一个main方法,将上面的代码new出了很多实例并且启动他们。结果我发现,我的电脑最多运行10个线程,如果运行10个以上,程序就会出错,跑不起来了。所以又去看了官网和网上的一些博客。

      要想多线程并发的运行WebDriver,必须同时满足2个条件,首先你的测试程序是多线程,其次需要用到Selenium Server。下载位置如下图:

      下载下来后是一个jar包,需要在命令行中运行。里面有2个东西:hub和node。可以这么理解:hub是运行在一个服务器上的线程池,负责收集测试case提交的请求,将请求分配给匹配的node;而node就是工作线程,具体干活的。node可以有多个,运行在不同的系统上。hub和node也可以不在一个机器上。

      多线程并发运行WebDriver的步骤:1.运行hub 2.运行node 3.运行test case 。下面说下具体实现方法。

      1.运行hub。在命令行中输入:java -jar selenium-server-standalone-2.37.0.jar -role hub -maxSession 40 -port 4444

    参数中必须指明-role hub 才是运行hub。默认端口是4444,如果端口被占用就需要指定其他。-maxSession是最大处理的会话请求,我这里设置为40。如果不指定的话,默认是1(即单线程模式了)。

      2.运行node。(先说下运行一个node情况)在命令行中输入(下面的命令是一行敲完):

    java -Dwebdriver.ie.driver=D:IEDriverServer.exe -jar selenium-server-standalone-2.37.0.jar -role node -hub http://127.0.0.1:4444/grid/register -maxSession 20 -browser "browserName=internet explorer,version=9,platform=WINDOWS,maxInstances=20" -port 5555

    由于node是可以运行在不通系统上的,所以指定驱动位置-Dwebdriver.ie.driver=D:IEDriverServer.exe。参数中必须指明-role node才是运行node。参数-hub 后面是第一步中hub的IP和端口:http://hub的IP:端口/grid/register  。node默认的maxSession的值就是5(最多并发5个浏览器),即启动一个node会默认有5个firefox、1个chrome、1个IE的实例。如果用IE浏览器的话,就算你的测试case是多线程,最终也会是一个一个的执行。但是如果在后面的-browser的参数中指明maxInstances=5,那么就会同时运行5个浏览器。-browser参数是指明node可以用的浏览器信息。注意,如果node的maxSession和maxInstances设置的有问题,那么hub的命令窗口中会给出警告。通过这里能够知道你的node是否设置成功。运行node后,窗口中也会显示该node的信息。-port是端口号,默认端口是5555,如果端口被占用就需要指定其他。如果你启动第二个node的话,端口就必须指定了,不能是5555。

      我设置的node是只运行IE,并且并发数是20,最多有20个IE浏览器在运行。node中的maxSession的值不能超过hub中的。如果想多线程并发要在hub和node的参数中同时指明maxSession值。node中如果用IE浏览器,指明maxSession后还需要指明同样大小的maxInstances值。我的例子最终会同时运行20个IE浏览器。maxSession是说node可以有几个浏览器同时运行,而maxInstances是说某个浏览器可以有几个同时运行。由于我的电脑运行20个IE已经有些卡了,那么可以再另外一个电脑上再运行一个20Session大小的node。个人测试结果:运行一个20Session大小的node和运行2个10Session大小的node没什么差别。运行多个node主要还是为了能够分布式的测试,不至于一个电脑打开太多浏览器。

      3.运行test case。首先将上面代码中的44和47行注释掉,将48行注释打开。我们需要用远程的方式将请求提交给hub(后面的/wd/hub是固定的)。

    WebDriver driver = new RemoteWebDriver(new URL("http://hub的IP:端口/wd/hub"),capability);

    由于是远程的方式,所以44行的设置就没什么用了。下面你可以运行你的程序了,你会发现同时启动20个线程,就会有20个IE浏览器同时在运行。

          

  • 相关阅读:
    pip不是内部或外部命令也不是可运行的程序或批处理文件的问题
    动态规划 leetcode 343,279,91 & 639. Decode Ways,62,63,198
    动态规划 70.climbing Stairs ,120,64
    (双指针+链表) leetcode 19. Remove Nth Node from End of List,61. Rotate List,143. Reorder List,234. Palindrome Linked List
    建立链表的虚拟头结点 203 Remove Linked List Element,82,147,148,237
    链表 206 Reverse Linked List, 92,86, 328, 2, 445
    (数组,哈希表) 219.Contains Duplicate(2),217 Contain Duplicate, 220(3)
    重装系统
    java常用IO
    端口
  • 原文地址:https://www.cnblogs.com/dingmy/p/3438084.html
Copyright © 2011-2022 走看看