自動化測試selenium在小公司的成功實踐

本文多是目前最完整的一篇selenium(java版)實踐文章,不是之一。
若是你是java開發人員,本文將幫助你快速搭建整套selenium自動化測試框架,你能夠幫助公司升級爲自動化測試架構;
若是你是測試人員,那你得按照本文多實踐一下,遇到不懂的諮詢下公司的java開發,一樣你也能夠完成自動化測試架構升級。
固然啦,若是目前公司已是自動化測試了,那本文就當是再次梳理下相關知識吧。
複製代碼

前言

可能提到自動化測試selenium,你們都會想到用python語言來編寫腳本。但咱們選擇了java語言,由於我相信大部分公司java程序員比python程序員多得多。而對於不少測試人員,並不能熟練使用編程語言,因此他們須要別人指導。與其使用更簡單的python語言,卻看不懂語法,得不到別人幫助;那還不如使用java語言,不管是語法仍是編程思路,均可以快速得到java開發人員的幫助。php

背景

可能不少公司已經有標準的後端單元測試代碼,可是自動化測試須要測試整個系統,前端是直接展現給用戶的,因此,前端尤其重要,本文就是基於h5的web前端自動化測試。固然啦,這裏推薦對項目進行先後端分離,若是項目沒有先後端分離可參考某小公司RESTful、共用接口、先後端分離、接口約定的實踐css

目前互聯網上關於selenium完整的文章不多,也很難買到一個專門講selenium的書籍,這讓不少測試人員無從下手,而本文會彌補這一問題,儘量詳細完整介紹selenium的實踐,提供一個簡易版的完整項目代碼在github上(由於公司項目代碼沒有脫敏,不能直接放到github上)。html

相關知識

  1. html標籤
  2. css樣式
  3. js基礎
  4. java基礎
  5. bat腳本基礎

首先html由標籤<x></x>組成,詳細本文會在真實項目中一一介紹。前端

正式實踐

安裝火狐瀏覽器

由於selenium在火狐瀏覽器裏,能夠自動化錄製腳本,咱們經過腳本錄製能夠生成出不一樣的語言腳本,能夠省去咱們90%的編寫腳本工做量。 能夠安裝最新版的火狐瀏覽器,而後安裝Katalon Recorder (Selenium IDE for Firefox) 使用火狐瀏覽器打開https://addons.mozilla.org/zh-CN/firefox/addon/katalon-automation-record/?src=searchjava

錄製腳本

以百度搜索掘金爲例python

  1. 地址欄打開百度
  2. 右上角,打開Katalon擴展
  3. 點擊Katalon的New
  4. 點擊 Record
  5. 網頁中輸入 掘金網
  6. 打開第一個掘金官網
  7. 在掘金官網搜索我之前寫的一篇文章 我是如何重構整個研發項目,促進自動化運維DevOps的落地?
  8. 點擊第一條 我是如何重構整個研發項目,促進自動化運維DevOps的落地?
  9. 點擊Katalon的stop

每執行一個操做右下角都會提示git

錄製後的效果圖

運行、分析腳本

錄製後,咱們點擊一下play,能夠看到火狐瀏覽器自動化的完成了咱們剛剛的操做(關閉彈窗阻止,或者將掘金和百度加入不阻止彈窗列表)程序員

點擊Exportgithub

能夠看到有各類語言 C#、Java、katalon、python2等。 咱們先看看python2的腳本web

# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest, time, re

class Test(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Firefox()
        self.driver.implicitly_wait(30)
        self.base_url = "https://www.katalon.com/"
        self.verificationErrors = []
        self.accept_next_alert = True
    
    def test_(self):
        driver = self.driver
        driver.get("https://www.baidu.com/index.php?tn=monline_3_dg")
        driver.find_element_by_id("kw").click()
        driver.find_element_by_id("kw").clear()
        driver.find_element_by_id("kw").send_keys(u"掘金網")
        driver.find_element_by_xpath("//div[@id='container']/div[2]/div").click()
        driver.find_element_by_link_text(u"掘金- juejin.im - 一個幫助開發者成長的社區").click()
        # ERROR: Caught exception [ERROR: Unsupported command [selectWindow | win_ser_1 | ]]
        driver.find_element_by_xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input").click()
        driver.find_element_by_xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input").click()
        driver.find_element_by_xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input").clear()
        driver.find_element_by_xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input").send_keys(u"我是如何重構整個研發項目,促進自動化運維DevOps的落地?")
        driver.find_element_by_xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input").send_keys(Keys.ENTER)
        driver.find_element_by_link_text(u"我是如何重構整個研發項目,促進自動化運維DevOps的落地?").click()
    
    def is_element_present(self, how, what):
        try: self.driver.find_element(by=how, value=what)
        except NoSuchElementException as e: return False
        return True
    
    def is_alert_present(self):
        try: self.driver.switch_to_alert()
        except NoAlertPresentException as e: return False
        return True
    
    def close_alert_and_get_its_text(self):
        try:
            alert = self.driver.switch_to_alert()
            alert_text = alert.text
            if self.accept_next_alert:
                alert.accept()
            else:
                alert.dismiss()
            return alert_text
        finally: self.accept_next_alert = True
    
    def tearDown(self):
        self.driver.quit()
        self.assertEqual([], self.verificationErrors)

if __name__ == "__main__":
    unittest.main()

複製代碼

咱們再看看java junit腳本

package com.example.tests;

import java.util.regex.Pattern;
import java.util.concurrent.TimeUnit;
import org.junit.*;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import org.openqa.selenium.*;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.Select;

public class Test {
  private WebDriver driver;
  private String baseUrl;
  private boolean acceptNextAlert = true;
  private StringBuffer verificationErrors = new StringBuffer();

  @Before
  public void setUp() throws Exception {
    driver = new FirefoxDriver();
    baseUrl = "https://www.katalon.com/";
    driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
  }

  @Test
  public void test() throws Exception {
    driver.get("https://www.baidu.com/index.php?tn=monline_3_dg");
    driver.findElement(By.id("kw")).click();
    driver.findElement(By.id("kw")).clear();
    driver.findElement(By.id("kw")).sendKeys("掘金網");
    driver.findElement(By.xpath("//div[@id='container']/div[2]/div")).click();
    driver.findElement(By.linkText("掘金- juejin.im - 一個幫助開發者成長的社區")).click();
    // ERROR: Caught exception [ERROR: Unsupported command [selectWindow | win_ser_1 | ]]
    driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).click();
    driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).click();
    driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).clear();
    driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).sendKeys("我是如何重構整個研發項目,促進自動化運維DevOps的落地?");
    driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).sendKeys(Keys.ENTER);
    driver.findElement(By.linkText("我是如何重構整個研發項目,促進自動化運維DevOps的落地?")).click();
  }

  @After
  public void tearDown() throws Exception {
    driver.quit();
    String verificationErrorString = verificationErrors.toString();
    if (!"".equals(verificationErrorString)) {
      fail(verificationErrorString);
    }
  }

  private boolean isElementPresent(By by) {
    try {
      driver.findElement(by);
      return true;
    } catch (NoSuchElementException e) {
      return false;
    }
  }

  private boolean isAlertPresent() {
    try {
      driver.switchTo().alert();
      return true;
    } catch (NoAlertPresentException e) {
      return false;
    }
  }

  private String closeAlertAndGetItsText() {
    try {
      Alert alert = driver.switchTo().alert();
      String alertText = alert.getText();
      if (acceptNextAlert) {
        alert.accept();
      } else {
        alert.dismiss();
      }
      return alertText;
    } finally {
      acceptNextAlert = true;
    }
  }
}

複製代碼

python代碼量明細比java要少一點,可是本文講java語言實踐。

咱們主要關注 java版 @Test註解的那個test方法

driver.get("https://www.baidu.com/index.php?tn=monline_3_dg");
    driver.findElement(By.id("kw")).click();
    driver.findElement(By.id("kw")).clear();
    driver.findElement(By.id("kw")).sendKeys("掘金網");
    driver.findElement(By.xpath("//div[@id='container']/div[2]/div")).click();
    driver.findElement(By.linkText("掘金- juejin.im - 一個幫助開發者成長的社區")).click();
    // ERROR: Caught exception [ERROR: Unsupported command [selectWindow | win_ser_1 | ]]
    driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).click();
    driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).click();
    driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).clear();
    driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).sendKeys("我是如何重構整個研發項目,促進自動化運維DevOps的落地?");
    driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).sendKeys(Keys.ENTER);
    driver.findElement(By.linkText("我是如何重構整個研發項目,促進自動化運維DevOps的落地?")).click();
複製代碼

可能不少人已經能看懂了

driver.get("https://www.baidu.com/index.php?tn=monline_3_dg");

打開百度

driver.findElement(By.id("kw")).click();

經過id定位到html標籤,而後點擊click();清空文本框.clear();輸入 掘金網3個字 sendKeys("掘金網");

這裏咱們看一下百度的搜索框代碼

<input type="text" class="s_ipt" name="wd" id="kw" maxlength="100" autocomplete="off">
複製代碼

driver.findElement(By.linkText("掘金- juejin.im - 一個幫助開發者成長的社區")).click();

單擊掘金網 經過linktext定位到標籤並點擊。

後面經過div=juejin一層一層定位到input,最後點擊進入文章。

認識html標籤

HTML <input>標籤

<input>標籤用於蒐集用戶信息。 根據不一樣的 type 屬性值,輸入字段擁有不少種形式。輸入字段能夠是文本字段、複選框、掩碼後的文本控件、單選按鈕、按鈕等等。

<form action="form_action.asp" method="get">
  First name: <input type="text" name="fname" />
  Last name: <input type="text" name="lname" />
  <input type="submit" value="Submit" />
</form>
複製代碼

詳情參考 http://www.w3school.com.cn/tags/tag_input.asp

HTML <a>標籤

<a> 標籤訂義超連接,用於從一張頁面連接到另外一張頁面。
<a> 元素最重要的屬性是 href 屬性,它指示連接的目標。
複製代碼

詳情參考http://www.w3school.com.cn/tags/tag_a.asp

HTML <div>標籤

<div>可定義文檔中的分區或節(division/section)。 <div>標籤能夠把文檔分割爲獨立的、不一樣的部分。它能夠用做嚴格的組織工具,而且不使用任何格式與其關聯。 若是用 id 或 class 來標記<div>,那麼該標籤的做用會變得更加有效。

<div style="color:#00FF00">
  <h3>This is a header</h3>
  <p>This is a paragraph.</p>
</div>
複製代碼

詳情參考http://www.w3school.com.cn/tags/tag_div.asp

…………

其餘標籤不一一介紹,可在參考網站上意義看

認識css

這裏只講1個關鍵的,好比

<div class="css1 css2"> ********</div>
複製代碼

表示這個div同時使用了css1和css2樣式,只須要知道若是沒辦法在selenium上定位的這個div,可以使用css名定位。

若是有興趣,可再看下其餘css相關知識。

js基礎

這裏講2個關鍵

<a onclick="test()">test</a>
複製代碼

上述代碼,點擊a標籤會執行js中的test方法,當selenium沒法定位到這個a標籤,能夠直接調用test()方法。

能夠寫簡單的js腳本,彈窗代碼:

alert("hello");
複製代碼

下載谷歌瀏覽器

下載谷歌瀏覽器,這裏可使用63.0.3239.84版本。 目前來講,谷歌瀏覽器版本兼容性仍是不錯的。

下載selenium driver

https://www.seleniumhq.org/download/

可不下,本文github項目中包含

下載selenium webdriver

https://npm.taobao.org/mirrors/chromedriver/ 需下載和谷歌瀏覽器對應的版本2.40 可不下,本文github項目中包含

下載idea開發工具

https://www.jetbrains.com/idea/

這個比較複雜,建議在java開發人員指導下完成。

selenium

這個版本是簡易版,但足夠

最終效果

咱們經過錄制selenium腳本,編輯,提交到git庫,由jenkins自動化編譯出jar包,經過bat命令在任意一臺pc端執行(默認開發人員提交代碼後自動執行全部模塊)。按功能模塊,測試項目,生成測試報告。對測試不經過的模塊

最大化

driver.manage().window().maximize();
複製代碼

打開頁面

driver.get("https://www.baidu.com");
複製代碼

定位元素

多個相同時,返回第一個,沒有找到會拋異常NoSuchElementException

WebElement element = driver.findElement(*);
複製代碼

當返回多個時:

List<WebElement> elements = driver.findElements(*);
複製代碼

定位元素方式

<input class="input_class input_class2" type="text" name="user-name" id="user-id" /> 
複製代碼

經過id定位

WebElement element = driver.findElement(By.id("user-id"));
複製代碼

經過name定位

WebElement element = driver.findElement(By.name("user-name"));
複製代碼

經過className定位

WebElement element = driver.findElement(By.className("input_class.input_class2"));
複製代碼

注意多個class用小數點隔開,也可使用cssSelector定位

WebElement element = driver.findElement(By.cssSelector("input"));
複製代碼

經過linkText定位,如:

WebElement element = driver.findElement(By.linkText("我是如何重構整個研發項目,促進自動化運維DevOps的落地?"));
複製代碼

意思就是連接內容定位

經過partialLinkText定位,模糊內容定位,和上類似

WebElement element = driver.findElement(By.linkText("我是如何重構整個研發項目?"));
複製代碼

經過tagName定位

WebElement element = driver.findElement(By.tagName("form"));
複製代碼

經過xpath定位

WebElement element = driver.findElement(By.xpath("//input[@id='passwd-id']")); 
複製代碼

這個最爲複雜,最簡單的版本是

//標籤類型[@屬性名=屬性值]
複製代碼

但也能夠定位第幾個

//input[4]
複製代碼

其中[]中還能夠增長邏輯and or表達式

WebElement element = driver.findElement(By.xpath("//input[@type='text' and @name='user-name']"));
WebElement element = driver.findElement(By.xpath("//input[@type='text' or @name='user-name']"));
複製代碼

[]中也能夠增長start-with、ends-with、contains,好比

WebElement element = driver.findElement(By.xpath("//input[start-with(@id,'user-')]"));
WebElement element = driver.findElement(By.xpath("//input[ends-with(@id,'user-')]"));
WebElement element = driver.findElement(By.xpath("//input[contains(@id,'user-')]"));
複製代碼

還能夠 任意屬性名

WebElement element = driver.findElement(By.xpath("//input[@*='user-name']"));
複製代碼

更多xpath使用方法見 http://www.w3school.com.cn/xpath/index.asp

單擊某個元素

.click()
複製代碼

清空input

.clear();
複製代碼

input中輸入內容

.sendKeys("掘金網");
複製代碼

若是是上傳附件,可直接sendKeys路徑

.sendKeys("c:\shao.png");
複製代碼

獲得input內容

.getText();
複製代碼

下拉框

Select select = new Select(driver.findElement(By.id("frequency")));
    select.selectByValue("1");
    driver.findElement(By.id("validDays")).click();
    
複製代碼
select.selectByValue("a"); 
    select.deselectAll();
    select.deselectByValue("a");
    select.deselectByVisibleText("");
    select.getAllSelectedOptions();
    select.getFirstSelectedOption(); 
複製代碼

單選框

WebElement radio=driver.findElement(By.id("radio"));
radio.click();&emsp;&emsp;&emsp;&emsp;   //選擇某個選項
radio.clear();&emsp;&emsp;&emsp;&emsp;  //清空選項
radio.isSelected();&emsp;&emsp;//判斷某個單選項是否被選中
複製代碼

複選框

WebElement checkbox = driver.findElement(By.id("checkbox"));
checkbox.clear();       //清空選項
checkbox.isSelected(); //是否選中
複製代碼

判斷是否可點擊

isEnabled()
複製代碼

alert框操做

Alert alert = driver.switchTo().alert();
alert.accept();&emsp;&emsp;//肯定
alert.dismiss();&emsp; //取消
複製代碼

iframe切換(重點

可能不少老的項目都有iframe,錄製腳本的時候正常錄製,可執行的時候,卻沒法執行,這個時候,須要切換iframe

driver.switchTo().defaultContent();&emsp;//回到默認的頁面
driver.switchTo().frame("leftFrame"); //切換到某個iframe
複製代碼

切換iframe,結束後,記得切換回默認頁面。

driver.findElement(By.linkText("導入模板")).click();
        WebElement iframe = driver.findElement(By.id("layui-layer-iframe1"));
        driver.switchTo().frame(iframe);
        Thread.sleep(2000);
        driver.findElement(By.linkText("引用")).click();
        driver.findElement(By.xpath("//button[@type='submit']")).click();
        driver.findElement(By.xpath("(//button[@type='button'])[3]")).click();
        Thread.sleep(1000);
        driver.findElement(By.linkText("學生")).click();
複製代碼

以上摘自項目代碼,僅供參考

執行 js

JavascriptExecutor js = (JavascriptExecutor) driver;
    js.executeScript("viewDetail('1f50555e409a4597a027ff415ce6c9b4','09','2018')");
複製代碼

執行內部viewDetail方法

延時操做(重要

不少時候咱們須要延時,這時使用

Thread.sleep(1000);//延時1000毫秒
複製代碼

許多錯誤是由於須要等待時間,嘗試增長一個延時,也許這個問題就過去了。

項目代碼

假設,咱們產品有多個環境,咱們定義一個environments數組,(當-1時,提示用戶輸入),有多個模塊(當-1時,提示用戶輸入),最終代碼以下,執行後,錯誤報告會經過郵件發送到指定郵箱或者其餘地方。

運行效果圖

import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import webfunction.*;

import java.util.Scanner;

public class Main {
    private static WebDriver driver;
    private static String baseUrl;
    private boolean acceptNextAlert = true;
    /**
     * 各個環境
     * */
    private static String[] environments = {"環境1", "環境2", "環境3", "環境4", "環境5", "環境6"};
    /**
     * 錯誤日誌
     * */
    private static StringBuffer verificationErrors = new StringBuffer();
    /**
     * 是否處於debug模式
     */
    private static boolean debug = false;
    /**
     * -1爲手動模式,不然爲指定數字
     * */
    private static String environment = "-1";
    /**
     * -1爲手動模式,不然爲指定數字
     * */
    private static String methods = "-1";

    public static void main(String[] args) throws Exception {
        //引用火狐瀏覽器驅動
        System.setProperty("webdriver.chrome.driver", "C:\\selenium\\chromedriver.exe");

        //定義用戶名密碼
        String uname, upw;
        Scanner sc = new Scanner(System.in);
        System.out.println("請選擇環境");
        for (int i = 0; i < environments.length; i++) {
            System.out.println(i + ":" + environments[i]);
        }
        if ("-1".equals(environment)) {
            environment = sc.next();
        }

        System.out.println("請輸入須要測試的功能,英文逗號隔開");
        if ("-1".equals(methods)) {
            methods = sc.next();
        }
        driver = new ChromeDriver();

        System.out.println("您選擇的是" + environments[Integer.valueOf(environment)]);
        switch (environment) {
            case "0":
                baseUrl = "http://*.*.*.*/";
                uname = "admin";
                upw = "admin";
                testManage(baseUrl, uname, upw, methods, driver);
                break;
            case "1":
                baseUrl = "http://*.*.*.*/";
                uname = "admin";
                upw = "admin";
                testManage(baseUrl, uname, upw, methods, driver);
                break;
            case "2":
                //等等等……
                break;
        }

    }

    private static void testManage(String url, String uname, String upw, String methods, WebDriver driver) throws InterruptedException {
        //先登陸管理端
        WebLogin.webLogin(driver, url, uname, upw);
        //而後測試全部模塊
        String[] strArray = null;
        strArray = methods.split(",");
        for (int i = 0; i < strArray.length; i++) {
            switch (strArray[i]) {
                case "0":
                    try {
                        // 系統基礎管理 - 用戶管理 - 新增用戶
                        WebSystemManage.addnewUser(driver, url);     
                    } catch (Exception e) {
                        verificationErrors.append("系統基礎管理 - 用戶管理 - 新增用戶 出錯");
                        log(e);
                    }
                    break;
                case "1":
                    try {
                        // 系統基礎管理 - 用戶管理 - 編輯用戶
                        WebSystemManage.editUser(driver, url);       
                    } catch (Exception e) {
                        System.out.println("系統基礎管理 - 用戶管理 - 編輯用戶 出錯");
                        log(e);
                    }
                    break;
                default:
                    break;
            }
        }
        report(verificationErrors);
    }

    private static void report(StringBuffer verificationErrors) {
        //發送郵件
    }

    /**
     * 根據debug變量是否輸出日誌
     * @param e
     */
    private static void log(Exception e) {
        if (debug) {
            e.printStackTrace();
        }
    }


    private static boolean isElementPresent(By by) {
        try {
            driver.findElement(by);
            return true;
        } catch (NoSuchElementException e) {
            return false;
        }
    }

    private static boolean isAlertPresent() {
        try {
            driver.switchTo().alert();
            return true;
        } catch (NoAlertPresentException e) {
            return false;
        }
    }

    private static String closeAlertAndGetItsText() {
        try {
            Alert alert = driver.switchTo().alert();
            String alertText = alert.getText();
            if (acceptNextAlert) {
                alert.accept();
            } else {
                alert.dismiss();
            }
            return alertText;
        } finally {
            acceptNextAlert = true;
        }
    }
}

複製代碼

代碼那麼多其實咱們只關注 public static void main(String[] args) throws Exception {}內的內容,好比,咱們想運行咱們最初錄製的掘金腳本,只需將那端我要求特別關注的代碼放到裏面便可,具體代碼以下:

import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;

public class Main {
    private static WebDriver driver;

    public static void main(String[] args) throws Exception {
        //引用火狐瀏覽器驅動
        System.setProperty("webdriver.chrome.driver", "C:\\selenium\\chromedriver.exe");
        driver = new ChromeDriver();
        driver.manage().window().maximize();
        //如下爲Katalon Recorder錄製後的腳本
        driver.get("https://www.baidu.com/index.php?tn=monline_3_dg");
        Thread.sleep(2000);
        driver.findElement(By.id("kw")).click();
        driver.findElement(By.id("kw")).clear();
        driver.findElement(By.id("kw")).sendKeys("掘金網");
        Thread.sleep(100);
        driver.findElement(By.id("su")).click();
        Thread.sleep(1000);
        driver.findElement(By.xpath("//div[@id='container']/div[2]/div")).click();
        driver.findElement(By.linkText("掘金- juejin.im - 一個幫助開發者成長的社區")).click();
        Thread.sleep(3000);
        // ERROR: Caught exception [ERROR: Unsupported command [selectWindow | win_ser_1 | ]]
        driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).click();
        driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).click();
        driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).clear();
        driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).sendKeys("我是如何重構整個研發項目,促進自動化運維DevOps的落地?");
        driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).sendKeys(Keys.ENTER);
        Thread.sleep(2000);
        driver.findElement(By.linkText("我是如何重構整個研發項目,促進自動化運維DevOps的落地?")).click();
    }
}

複製代碼

上述代碼中註釋內是Katalon Recorder導出的腳本,可是咱們增長了一些延時操做,selenium延時有很3種:普通sleep、顯示等待方式、隱式等待方式。這裏先簡單粗暴一下,用Thread.sleep(*);延時,好比打開百度延時2秒、輸入「掘金網」延時100毫秒、搜索後延時3秒…………

很遺憾,咱們代碼報錯:

大概意思說超時沒有找到那個搜索框,因爲各類各樣的緣由,會致使咱們在火狐瀏覽器中錄製的腳本在java代碼中的谷歌瀏覽器裏沒法兼容,這個時候咱們須要去分析一下具體邏輯。

這裏是因爲新窗口須要切換window,可以使用下述代碼切換(替換代碼中// ERROR: Caught exception [ERROR: Unsupported command [selectWindow | win_ser_1 | ]]這行便可)。

Set<String> windowHandles = driver.getWindowHandles();
        String windowHandle = driver.getWindowHandle();
        for (String handle : windowHandles) {
            if (!handle.equals(driver.getWindowHandle())) {
                driver.switchTo().window(handle);
                break;
            }
        }
複製代碼

導出的腳本By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")這一句很複雜,咱們試着簡化它。

<input data-v-5ce25e66="" maxlength="32" placeholder="搜索掘金" class="search-input">
複製代碼

首先搜索下search-input樣式,看該頁面是否只有一個search-input樣式。

果真search-input樣式只有一個標籤。

因而咱們將

By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")
//改成
By.className("search-input")
複製代碼

最終代碼

import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;

import java.util.Set;

public class Main {
    private static WebDriver driver;

    public static void main(String[] args) throws Exception {
        //引用火狐瀏覽器驅動
        System.setProperty("webdriver.chrome.driver", "C:\\selenium\\chromedriver.exe");
        driver = new ChromeDriver();
        driver.manage().window().maximize();
        driver.get("https://www.baidu.com/index.php?tn=monline_3_dg");
        Thread.sleep(2000);
        driver.findElement(By.id("kw")).click();
        driver.findElement(By.id("kw")).clear();
        driver.findElement(By.id("kw")).sendKeys("掘金網");
        Thread.sleep(100);
        driver.findElement(By.id("su")).click();
        Thread.sleep(1000);
        driver.findElement(By.xpath("//div[@id='container']/div[2]/div")).click();
        driver.findElement(By.linkText("掘金- juejin.im - 一個幫助開發者成長的社區")).click();
        Thread.sleep(7000);
        Set<String> windowHandles = driver.getWindowHandles();
        String windowHandle = driver.getWindowHandle();
        for (String handle : windowHandles) {
            if (!handle.equals(driver.getWindowHandle())) {
                driver.switchTo().window(handle);
                break;
            }
        }
        // ERROR: Caught exception [ERROR: Unsupported command [selectWindow | win_ser_1 | ]]
        driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).click();
        driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).click();
        driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).clear();
        driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).sendKeys("我是如何重構整個研發項目,促進自動化運維DevOps的落地?");
        driver.findElement(By.xpath("//div[@id='juejin']/div[2]/div/header/div/nav/ul/li[2]/form/input")).sendKeys(Keys.ENTER);
        Thread.sleep(2000);
        driver.findElement(By.linkText("我是如何重構整個研發項目,促進自動化運維DevOps的落地?")).click();
    }
}
複製代碼

編譯打包

獲得selenium.jar包,可複製到C:\selenium下,和chromedriver.exe同級。
輸入cmd命令

C:\Users\Administrator>cd C:\selenium

C:\selenium>java -jar selenium2.jar
複製代碼

便可自動化運行,非windows系統下載2.40其餘版本https://npm.taobao.org/mirrors/chromedriver/2.40/

github項目運行

https://github.com/qq273681448/selenium

爲了防止有讀者沒有改maven庫鏡像,因此把lib包都放在項目中了。直接使用idea打開,可能有些配置須要改,可參考

寫在最後

至此,一個基礎版的selenium框架就搭好了,後續,能夠鏈接數據庫,從庫中隨機取出賬號,進行項目測試。也能夠配合bat腳本,實現自動化測試以及報告生成。

相關文章
相關標籤/搜索