Selenium3與Python3實戰 Web自動化測試框架(一)


Selenium3與Python3實戰 Web自動化測試框架


一、環境搭建

1、selenium環境搭建

Client:

  •  pycharm
  •  python3.6

Driver:

  •  Chrome → ChromeDriver
  •  Firefox  → FirefoxDriver
  •  IE         → InternetExplorerDriver

Selenium


 

1.1、Selenium安裝

pip install selenium  # 安裝
from selenium import webdriver # 導入
driver = webdriver.Chrome() # 啟動谷歌瀏覽器
driver.get("http://www.baidu.com") # 打開百度網址
# 注意:啟動谷歌瀏覽器前需要配置好谷歌瀏覽器中間件 ,從網上下載chromedriver.exe ,將其放置到python的安裝目錄下

1.2、使用腳本啟動不同瀏覽器

啟動瀏覽器前需配置好瀏覽器對應driver:

  • Chrome --chromedriver.exe :谷歌瀏覽器調試驅動插件
  • Firefox --geckodrive.exe : 火狐瀏覽器調試驅動插件
  • IE --MicrosoftWebDriver.exe : IE瀏覽器調試驅動插件

將上面三個exe文件下載后放置到python目錄下

1)啟動谷歌瀏覽器

from selenium import webdriver

driver = webdriver.Chrome()
driver.get('http://www.baidu.com')

 

2)啟動火狐瀏覽器:

from selenium import webdriver

driver = webdriver.Firefox()
driver.get('http://www.baidu.com')

 

3)啟動IE瀏覽器

from selenium import webdriver

driver = webdriver.Ie()
# driver = webdriver.Edge()  # win 10版本啟動IE瀏覽器,使用此行代碼
driver.get('http://www.baidu.com')

 

2、使用expected_condition下的 title_contains判斷頁面標題是否與我們想要的一致,如判斷頁面標題是否有‘注冊’字眼:

from selenium import webdriver
from selenium.webdriver.support import expected_conditions
import time

driver = webdriver.Chrome()
# driver = webdriver.Edge()  # win 10版本啟動IE瀏覽器,使用此行代碼
driver.get('http://www.5itest.cn/register')
time.sleep(5)
is_live = expected_conditions.title_contains('注冊')  # 判斷頁面的標題中是否有注冊兩字
print('is_live:',is_live)

 

返回結果:

is_live: <selenium.webdriver.support.expected_conditions.title_contains object at 0x000000000354DEF0>  # 存在

 

3、使用不同方式進行定位

訪問注冊鏈接:http://www.5itest.cn/register ,進行測試

 

from selenium import webdriver

driver = webdriver.Chrome()
driver.get('http://www.5itest.cn/register')
driver.find_element_by_id('register_email').send_keys("nan@163.com")  # 填寫郵箱
user_name_node = driver.find_elements_by_class_name('controls')[1]  # 使用classname進行定義,需要細心處理
user_name_node.find_element_by_class_name('form-control').send_keys('Eric_nan')  # 填寫用戶名
driver.find_element_by_name('password').send_keys('111111')  # 填寫密碼
driver.find_element_by_xpath('//*[@id="captcha_code"]').send_keys('2222')  # 填寫驗證碼

 

腳本控制啟動瀏覽器並訪問注冊頁面,同時自動輸入我們設定的值:

 


 

4、使用expected_conditions判斷元素是否可見

from selenium import webdriver
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()

locator = (By.CLASS_NAME,'controls')  # 通過classname的方式 找到 controls
WebDriverWait(driver,1).until(expected_conditions.visibility_of_element_located(locator))
# WebDriverWait: 傳入兩個參數,一個是driver,另一個是超時時間(int類型)
# visibility_of_element_located:只在可見的元素里找對應的元素。如有返回內存地址

 

 5、如何解決驗證碼自動輸入

 1)將注冊頁面全屏截圖保存(使用driver.save_screenhot方法),再將驗證碼部分區域截圖保存下來

打開本地圖片、截取部分區域需要用到PIL ,安裝:pip install -i https://pypi.douban.com/simple Pillow

driver = webdriver.Chrome()

base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 項目首路徑
image_path = os.path.join(base_dir,'Image','imooc.png')  # 圖片路徑,用於保存全屏截圖后的圖片
code_path = os.path.join(base_dir,'Image','code.png')  # 驗證碼圖片保存路徑

driver.get('http://www.5itest.cn/register')
driver.save_screenshot(image_path)  # 全屏截圖
code_element = driver.find_element_by_id("getcode_num") # 定位到驗證碼所在的文字
# print(code_element.location)   # 獲取該元素(圖片)左上角的(x,y)坐標
# print(code_element.size)   # 獲取該元素(圖片)長度、寬度
left_x = code_element.location['x'] # 左上角x值
top_y = code_element.location['y'] # 左上角y值
right_x = left_x + code_element.size['width']  # 右下角x值
right_y = top_y + code_element.size['height']  # 右下角y值

im = Image.open(image_path) # 使用PIL下的Image打開下載的imooc.png圖片
img = im.crop((left_x,top_y,right_x,right_y))  # 將指定的某部分裁剪出來
img.save(code_path) # 保存

 

 2)使用 showapiRequest解決圖片驗證碼識別

 ①、使用pytesseract識別圖片中得問題

  安裝:pip install pytesseract

import pytesseract
from PIL import Image

image = Image.open("E:/imooc2.png")
text = pytesseract.image_to_string(image) # 將圖片文字轉換成字符串
print(text)

# 缺點:機械性讀取,無法讀取圖片中不規則的字體,不適合於干擾性比較強的驗證碼圖片文字讀取

 

②、 使用 showapiRequest解決圖片驗證碼識別(需收費,每測試識別一次都會收取費用,低至0.01)

 進入萬維易源網:https://www.showapi.com/api/view/184/4

 選擇:驗證碼識別英數_文件 ,找到請求示例,下載SDK:ShowapiRequest.py

 

將 ShowapiRequest.py文件放到項目中,新建read_code_img.py文件,用於讀取圖片中的驗證碼:

 驗證碼:

from setting.ShowapiRequest import ShowapiRequest
from setting import setting


r = ShowapiRequest("http://route.showapi.com/184-4","62666","d61950be50dfgjnr9969f741b8e730f5" )
# ShowapiRequest 的第一個參數是萬維易源網的url ,第二個參數是易源網上你個人的appId , 第三個參數是易源網上的密鑰
r.addBodyPara("typeId", "35") #typeId:表示識別幾位數的圖片驗證碼 ;35:'3'表示英數結合的驗證碼,'5'表示5位數的驗證碼 ; 31:一位數的驗證碼 r.addBodyPara("convert_to_jpg", "0") r.addFilePara("image", setting.code_path) # 添加要識別驗證碼的圖片 res = r.post() print(res.text) # {"showapi_res_error":"","showapi_res_id":"6f0e4cdb977141b293ea12178ad3d37e","showapi_res_code":0,"showapi_res_body":{"Id":"5bac83cc-5637-4e2d-bc91-25a78b527241","Result":"ANLZZ","ret_code":0}} text = res.json()['showapi_res_body']['Result']# 以json格式讀取:showapi_res_body 下 Result 的值 print(text) # 返回信息:ANLZZ (識別正確)

 注:這種方式識別准確率比較高


 

 將注冊相關代碼封裝起來-初次封裝

from selenium import webdriver
from setting.ShowapiRequest import ShowapiRequest
from setting import setting
from PIL import Image

import time
import random

class Register_Operate(object):
    def __init__(self,file_name):
        # 瀏覽器初始化
        self.driver = webdriver.Chrome()
        self.driver.get('http://www.5itest.cn/register')
        self.driver.maximize_window() # 窗口最大化
        self.file_name = file_name

    def get_element(self,id):
        # 獲取element信息
        element = self.driver.find_element_by_id(id)
        return element

    def get_range_for_user(self):
        # 獲取隨機字符串,用於郵箱隨機輸入、用戶名隨機輸入
        user_info = ''.join(random.sample('1234567890abcdefghijklmn',9))
        return user_info


    def get_code_image(self):
        # 獲取驗證碼圖片,並保存到file_name中
        self.driver.save_screenshot(self.file_name)  # 全屏截圖,保存到file_name
        code_element = self.get_element("getcode_num")  # 定位到驗證碼所在的文字
        # print(code_element.location)   # 獲取該元素(圖片)左上角的(x,y)坐標
        # print(code_element.size)   # 獲取該元素(圖片)長度、寬度
        left_x = code_element.location['x']  # 左上角x值
        top_y = code_element.location['y']  # 左上角y值
        right_x = left_x + code_element.size['width']  # 右下角x值
        right_y = top_y + code_element.size['height']  # 右下角y值

        im = Image.open(self.file_name)  # 使用PIL下的Image打開下載的imooc.png圖片
        img = im.crop((left_x, top_y, right_x, right_y))  # 將指定的某部分裁剪出來(驗證碼圖片)
        img.save(self.file_name)  # 保存到file_name中


    def code_online(self):
        # 將file_name中的驗證碼圖片進行識別,用於注冊時驗證碼輸入
        r = ShowapiRequest("http://route.showapi.com/184-4", "62626", "d61950be50dc4dbd9969f741b8e730f5")
        r.addBodyPara("typeId", "35")  # typeId:表示識別幾位數的圖片驗證碼 ;35:'3'表示英數結合的驗證碼,'5'表示5位數的驗證碼   ; 31:一位數的驗證碼
        r.addBodyPara("convert_to_jpg", "0")
        r.addFilePara("image", self.file_name)  # 添加要識別驗證碼的圖片,image:圖片格式,setting.code_path:圖片位置
        res = r.post()
        # print(res.text)  # {"showapi_res_error":"","showapi_res_id":"6f0e4cdb977141b293ea12178ad3d37e","showapi_res_code":0,"showapi_res_body":{"Id":"5bac83cc-5637-4e2d-bc91-25a78b527241","Result":"ANLZZ","ret_code":0}}
        code_text = res.json()['showapi_res_body']['Result']  # 以json格式讀取:showapi_res_body 下 Result 的值
        # print(code_text)
        return code_text

    def run_main(self):
        # 主程序
        user_name = self.get_range_for_user()  # 用戶名
        user_email = user_name + '@163.com'  # 郵箱
        self.get_element("register_email").send_keys(user_email)  # 定位郵箱,並自動輸入隨機獲取的郵箱號
        self.get_element("register_nickname").send_keys(user_name)  # 自動輸入用戶名
        self.get_element("register_password").send_keys("111111")  # 自動輸入密碼
        self.get_code_image()  # 獲取驗證碼圖片,保存於服務器
        code_text = self.code_online() # 識別驗證碼圖片,獲取驗證碼
        print(code_text)
        self.get_element("captcha_code").send_keys(code_text)  # 自動輸入驗證碼
        self.get_element("register-btn").click()  # 注冊按鈕
        self.driver.close()   # 關閉瀏覽器
        time.sleep(3)
        self.driver.close()


if __name__ == "__main__":
    file_name = setting.code_path
    register_oper = Register_Operate(file_name)  # 實例化
    # time.sleep(1)
    register_oper.run_main()  # 運行主程序
注冊自動輸入對應信息

 6、封裝讀取配置文件方法

 新建int配置文件:

#localElement.ini文件

[RegisterElement]
user_email=id>register_email
user_email_error=id>register_email-error
user_name=id>register_nickname
user_name_error=id>register_nickname-error
password=id>register_password
password_error=id>register_password-error
code_image=id>getcode_num
code_text=id>captcha_code
code_text_error=id>captcha_code-error
register_button=id>register-btn

 

使用python3自帶 configparser模塊, 用於讀取配置文件信息:

from setting.setting import config_ini_dir
import configparser

class Read_Ini(object): # 初始化
    def __init__(self,node = None):
        if node:
            self.node = node
        else:
            self.node = 'RegisterElement'  # 配置文件中的某個節點
        self.cf = self.load_ini()

    def load_ini(self):  # 加載文件
        cf = configparser.ConfigParser()  # 使用 configparser模塊讀取配置文件信息
        cf.read(config_ini_dir)  # 配置文件所在路徑
        return cf

    def get_value(self,key): # 獲取配置文件中key的value值
        data = self.cf.get(self.node,key)
        return data

# if __name__ == '__main__':
#     read_init = Read_Ini()
#     print(read_init.get_value('user_name'))  # 結果:id>register_nickname
 
        

 

7、封裝定位元素類

# find_element.py
from util.read_ini import Read_Ini
class FindElement(object):
    def __init__(self,driver):
        self.driver = driver
    def get_element(self,key):
        read_ini = Read_Ini()
        data = read_ini.get_value(key)
        by,value = data.split('>')

        try:
            if by == 'id':
                return self.driver.find_element_by_id(value)
            elif by == 'name':
                return self.driver.find_element_by_name(value)
            elif by == 'className':
                return self.driver.find_element_by_class_name(value)
            elif by == 'xpath':
                return self.driver.find_element_by_xpath(value)
            else:
                return self.driver.find_element_by_css(value)
        except Exception as e:
            print("find_element錯誤信息:",e)
            return None

 


 

* 注冊完整流程

1、配置文件

1)LocalElement.ini:存定位元素信息

[RegisterElement]
user_email=id>register_email
user_email_error=id>register_email-error
user_name=id>register_nickname
user_name_error=id>register_nickname-error
password=id>register_password
password_error=id>register_password-error
code_image=id>getcode_num
code_text=id>captcha_code
code_text_error=id>captcha_code-error
register_button=id>register-btn
LocalElement.ini

 

2)setting.py:

import os

base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 項目首路徑
codeerror_path = os.path.join(base_dir,'Image','codeerror.png')  # 驗證碼錯誤圖片路徑
code_path = os.path.join(base_dir,'Image','code.png')  # 驗證碼圖片保存路徑
config_ini_dir = os.path.join(base_dir,'setting','localElement.ini')  # localElement.ini 配置文件路徑
setting.py

 

3)read_ini.py:讀取配置文件LocalElement.py的配置信息

from setting.setting import config_ini_dir
import configparser

class Read_Ini(object): # 初始化
    def __init__(self,node = None):
        if node:
            self.node = node
        else:
            self.node = 'RegisterElement'  # 配置文件中的某個節點
        self.cf = self.load_ini()

    def load_ini(self):  # 加載文件
        cf = configparser.ConfigParser()  # 使用 configparser模塊讀取配置文件信息
        cf.read(config_ini_dir)  # 配置文件所在路徑
        return cf

    def get_value(self,key): # 獲取配置文件中key的value值
        data = self.cf.get(self.node,key)
        return data
read_ini.py

 

4)find_element.py:獲取元素定位信息

from util.read_ini import Read_Ini
class FindElement(object):
    def __init__(self,driver):
        self.driver = driver
    def get_element(self,key):
        read_ini = Read_Ini()
        data = read_ini.get_value(key)
        by,value = data.split('>')

        try:
            if by == 'id':
                return self.driver.find_element_by_id(value)
            elif by == 'name':
                return self.driver.find_element_by_name(value)
            elif by == 'className':
                return self.driver.find_element_by_class_name(value)
            elif by == 'xpath':
                return self.driver.find_element_by_xpath(value)
            else:
                return self.driver.find_element_by_css(value)
        except Exception as e:
            # print("find_element錯誤信息:",e)
            return None
find_element.py

 

5)register_function.py:注冊測試主程序

from selenium import webdriver
from setting.ShowapiRequest import ShowapiRequest
from setting import setting
from PIL import Image
from base.find_element import FindElement

import time
import random

"""用於注冊測試,自動識別驗證碼,自動定位form表單位置,進行對應數據自動輸入"""
class RegisterFunction(object):
    def __init__(self,file_name,url,i,codeerror_name):
        # 瀏覽器初始化
        self.i = i
        self.url = url
        self.file_name = file_name # 驗證碼圖片保存路徑
        self.codeerror_name = codeerror_name  # 驗證碼錯誤圖片截圖保存路徑
        self.driver = self.get_driver()

    def get_driver(self): # 啟動瀏覽器類型
        if self.i == 1:
            driver = webdriver.Chrome()
        elif self.i == 2:

            driver = webdriver.Firefox()
        else:
            driver = webdriver.Edge()
        driver.get(self.url)
        driver.maximize_window()
        return driver

    def get_user_element(self,key):
        # 定位元素位置,獲取對應element
        find_element = FindElement(self.driver)
        user_element = find_element.get_element(key)  # key為LocalElement 中的value值,如:id>register_email ; user_element:register_email
        return user_element


    def send_user_info(self, key, data):
        # 輸入注冊時所需用戶信息
        # get_user_element:定位到元素所在位置 ,send_keys:發送數據,讓頁面自動填寫信息
        self.get_user_element(key).send_keys(data)


    def get_range_for_user(self):
        # 獲取隨機字符串,用於郵箱隨機輸入、用戶名隨機輸入
        user_info = ''.join(random.sample('1234567890abcdefghijklmn',9))
        return user_info


    def get_code_image(self):
        # 獲取驗證碼圖片,並保存到file_name中
        self.driver.save_screenshot(self.file_name)  # 全屏截圖,保存到file_name
        code_element = self.get_user_element("code_image")  # 定位到驗證碼圖片所在的區域
        left_x = code_element.location['x']  # 左上角x值
        top_y = code_element.location['y']  # 左上角y值
        right_x = left_x + code_element.size['width']  # 右下角x值
        right_y = top_y + code_element.size['height']  # 右下角y值

        im = Image.open(self.file_name)  # 使用PIL下的Image打開下載的imooc.png圖片
        img = im.crop((left_x, top_y, right_x, right_y))  # 將指定的某部分裁剪出來(驗證碼圖片)
        img.save(self.file_name)  # 保存到file_name中


    def code_online(self):
        # 將file_name中的驗證碼圖片進行識別,用於注冊時驗證碼輸入
        r = ShowapiRequest("http://route.showapi.com/184-4", "62626", "d61950be50dc4dbd9969f741b8e730f5")
        r.addBodyPara("typeId", "35")  # typeId:表示識別幾位數的圖片驗證碼 ;35:'3'表示英數結合的驗證碼,'5'表示5位數的驗證碼   ; 31:一位數的驗證碼
        r.addBodyPara("convert_to_jpg", "0")
        r.addFilePara("image", self.file_name)  # 添加要識別驗證碼的圖片,image:圖片格式,setting.code_path:圖片位置
        res = r.post()
        # print(res.text)  # {"showapi_res_error":"","showapi_res_id":"6f0e4cdb977141b293ea12178ad3d37e","showapi_res_code":0,"showapi_res_body":{"Id":"5bac83cc-5637-4e2d-bc91-25a78b527241","Result":"ANLZZ","ret_code":0}}
        code_text = res.json()['showapi_res_body']['Result']  # 以json格式讀取:showapi_res_body 下 Result 的值
        # print(code_text)
        return code_text

    def run_main(self):
        # 主程序
        user_name = self.get_range_for_user()  # 用戶名
        user_email = user_name + '@163.com'  # 郵箱
        self.send_user_info('user_email', user_email)  # 定位郵箱,並自動輸入隨機獲取的郵箱號
        self.send_user_info('user_name', user_name)  # 自動輸入用戶名
        self.send_user_info('password', "111111")  # 自動輸入密碼
        self.get_code_image()  # 獲取驗證碼圖片,保存於服務器
        code_text = self.code_online() # 識別驗證碼圖片,獲取驗證碼
        print(code_text)
        self.send_user_info("code_text",code_text)  # 自動輸入驗證碼
        # self.send_user_info("code_text",11111)  # 自動輸入驗證碼
        self.get_user_element("register_button").click()  # 注冊按鈕
        code_error = self.get_user_element("code_text_error") # 定位到驗證碼錯誤信息位置,如果返回None,表示定位失敗,驗證碼沒有錯誤
        if code_error == None:
            print("注冊成功")
        else:
            self.driver.save_screenshot(codeerror_name)
        time.sleep(3)
        self.driver.close()


if __name__ == "__main__":
    file_name = setting.code_path
    codeerror_name = setting.codeerror_path
    url = 'http://www.5itest.cn/register'
    register_func = RegisterFunction(file_name,url,1,codeerror_name)  # 實例化
    register_func.run_main()  # 運行主程序
register_function.py

 


 


免責聲明!

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



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