当前位置:网站首页>UI automation test: selenium+po mode +pytest+allure integration
UI automation test: selenium+po mode +pytest+allure integration
2022-07-03 21:02:00 【Little brother said test】
I am not involved in WebUI automated testing , But in order to improve their technology , There is no harm in learning more , No more nonsense , At present, the mainstream webUI The test framework should still be selenium, Considering maintainability 、 Expansibility 、 Reusability, etc , We use PO Pattern to write our script , This document also mainly integrates Selenium+PO Pattern +Pytest+Allure, Now let's get to the point . notes : At the end of the article Github Address
Technical premise :python、selenium、pytest Basic knowledge of
1. Project structure catalog :
2. PO Model is introduced
PO Model features :
- Easy to maintain
- High reusability
- The script is easy to read and understand
PO Model elements :
1. stay PO The pattern is abstractly encapsulated into a BasePage class , The base class should have one that only implements webdriver Properties of instances
2. Each one pag inherit BasePage, adopt driver To manage Ben page The element in the will page The operations in are encapsulated into methods one by one
3. TestCase rely on page class , So as to achieve the corresponding test steps
3. BasePage Page encapsulation
import logging
import os
import time
from datetime import datetime
from time import sleep
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from Utils.myLog import MyLog
"""
This class encapsulates all operations , All pages inherit this class
"""
class BasePage(object):
def __init__(self, driver):
self.logger = MyLog().getLog()
self.driver = driver
# Wait for the element to be visible
def wait_eleVisible(self, loc, timeout=30, poll_frequency=0.5, model=None):
"""
:param loc: Element location expression ; A tuple type , The way of expression ( Element location type , Element positioning method )
:param timeout: The upper limit of waiting
:param poll_frequency: Polling frequency
:param model: Wait for failure , Screenshot operation , The function annotation to be expressed in the picture file
:return:None
"""
self.logger.info(f' wait for "{model}" Elements , Positioning mode :{loc}')
try:
start = datetime.now()
WebDriverWait(self.driver, timeout, poll_frequency).until(EC.visibility_of_element_located(loc))
end = datetime.now()
self.logger.info(f' wait for "{model}" Duration :{end - start}')
except TimeoutException:
self.logger.exception(f' wait for "{model}" Element failed , Positioning mode :{loc}')
# Screenshot
self.save_webImgs(f" Waiting elements [{model}] Something unusual happened ")
raise
# Wait for the element to be invisible
def wait_eleNoVisible(self, loc, timeout=30, poll_frequency=0.5, model=None):
"""
:param loc: Element location expression ; A tuple type , The way of expression ( Element location type , Element positioning method )
:param timeout: The upper limit of waiting
:param poll_frequency: Polling frequency
:param model: Wait for failure , Screenshot operation , The function annotation to be expressed in the picture file
:return:None
"""
logging.info(f' wait for "{model}" disappear , Element localization :{loc}')
try:
start = datetime.now()
WebDriverWait(self.driver, timeout, poll_frequency).until_not(EC.visibility_of_element_located(loc))
end = datetime.now()
self.logger.info(f' wait for "{model}" Duration :{end - start}')
except TimeoutException:
self.logger.exception(f' wait for "{model}" Element failed , Positioning mode :{loc}')
# Screenshot
self.save_webImgs(f" Waiting elements [{model}] Disappear abnormally ")
raise
# Find an element element
def find_element(self, loc, model=None):
self.logger.info(f' lookup "{model}" Elements , Element localization :{loc}')
try:
return self.driver.find_element(*loc)
except NoSuchElementException:
self.logger.exception(f' lookup "{model}" Element failed , Positioning mode :{loc}')
# Screenshot
self.save_webImgs(f" Look for the element [{model}] abnormal ")
raise
# Look for the element elements
def find_elements(self, loc, model=None):
self.logger.info(f' lookup "{model}" Set of elements , Element localization :{loc}')
try:
return self.driver.find_elements(*loc)
except NoSuchElementException:
self.logger.exception(f' lookup "{model}" Element set failed , Positioning mode :{loc}')
# Screenshot
self.save_webImgs(f" Find element set [{model}] abnormal ")
raise
# Input operation
def input_text(self, loc, text, model=None):
# Look for the element
ele = self.find_element(loc, model)
# Input operation
self.logger.info(f' stay "{model}" Input "{text}", Element localization :{loc}')
try:
ele.send_keys(text)
except:
self.logger.exception(f'"{model}" Input operation failed !')
# Screenshot
self.save_webImgs(f"[{model}] Input exception ")
raise
# Clear operation
def clean_inputText(self, loc, model=None):
ele = self.find_element(loc, model)
# Clear operation
self.logger.info(f' eliminate "{model}", Element localization :{loc}')
try:
ele.clear()
except:
self.logger.exception(f'"{model}" Clear operation failed ')
# Screenshot
self.save_webImgs(f"[{model}] Clear exceptions ")
raise
# Click on the action
def click_element(self, loc, model=None):
# First find the element and click
ele = self.find_element(loc, model)
# Click on the action
self.logger.info(f' Click on "{model}", Element localization :{loc}')
try:
ele.click()
except:
self.logger.exception(f'"{model}" Click failed ')
# Screenshot
self.save_webImgs(f"[{model}] Click exception ")
raise
# Get text content
def get_text(self, loc, model=None):
# Find the element first and get the text content
ele = self.find_element(loc, model)
# Get text
self.logger.info(f' obtain "{model}" Element text content , Element localization :{loc}')
try:
text = ele.text
self.logger.info(f' obtain "{model}" The text content of the element is "{text}", Element localization :{loc}')
return text
except:
self.logger.exception(f' obtain "{model}" Element text content failed , Element localization :{loc}')
# Screenshot
self.save_webImgs(f" obtain [{model}] The text content is abnormal ")
raise
# Get attribute value
def get_element_attribute(self, loc, name, model=None):
# First find the element to get the attribute value
ele = self.find_element(loc, model)
# Get element attribute value
self.logger.info(f' obtain "{model}" Element attributes , Element localization :{loc}')
try:
ele_attribute = ele.get_attribute(name)
self.logger.info(f' obtain "{model}" Elements "{name}" The property set is "{ele_attribute}", Element localization :{loc}')
return ele_attribute
except:
self.logger.exception(f' obtain "{model}" Elements "{name}" Property failed , Element localization :{loc}')
# Screenshot
self.save_webImgs(f" obtain [{model}] Property exception ")
raise
# iframe Switch
def switch_iframe(self, frame_refer, timeout=30, poll_frequency=0.5, model=None):
# wait for iframe There is
self.logger.info('iframe Switching operation :')
try:
# Switch == index\name\id\WebElement
WebDriverWait(self.driver, timeout, poll_frequency).until(
EC.frame_to_be_available_and_switch_to_it(frame_refer))
sleep(0.5)
self.logger.info(' Switch successful ')
except:
self.logger.exception('iframe Switch failed !!!')
# Screenshot
self.save_webImgs(f"iframe Switching exception ")
raise
# Window switch = If you are switching to a new window ,new. If it is to return to the default window ,default
def switch_window(self, name, cur_handles=None, timeout=20, poll_frequency=0.5, model=None):
"""
Get... Before calling window_handles
:param name: new Represents the latest open window . default Represents the first window . Other values are expressed as the window's handles
:param cur_handles:
:param timeout: The upper limit of waiting
:param poll_frequency: Polling frequency
:param model: Wait for failure , Screenshot operation , The function annotation to be expressed in the picture file
:return:
"""
try:
if name == 'new':
if cur_handles is not None:
self.logger.info(' Switch to the latest open window ')
WebDriverWait(self.driver, timeout, poll_frequency).until(EC.new_window_is_opened(cur_handles))
window_handles = self.driver.window_handles
self.driver.swich_to.window(window_handles[-1])
else:
self.logger.exception(' Switch failed , There is no information to switch windows !!!')
self.save_webImgs(" Switch failed _ There is no information to switch windows ")
raise
elif name == 'default':
self.logger.info(' Switch to the default page ')
self.driver.switch_to.default()
else:
self.logger.info(' Switch to handles The window of ')
self.driver.swich_to.window(name)
except:
self.logger.exception(' Failed to switch windows !!!')
# Screenshot
self.save_webImgs(" Switch failed _ There is no information to switch windows ")
raise
# Screenshot
def save_webImgs(self, model=None):
# filepath = Refers to the image storage directory /model( Page function name )_ The current time is seconds .png
# Screenshot save Directory
# Splice log folder , If it doesn't exist, it will be created automatically
cur_path = os.path.dirname(os.path.realpath(__file__))
now_date = time.strftime('%Y-%m-%d', time.localtime(time.time()))
screenshot_path = os.path.join(os.path.dirname(cur_path), f'Screenshots\\{now_date}')
if not os.path.exists(screenshot_path):
os.mkdir(screenshot_path)
# current time
dateNow = time.strftime('%Y%m%d_%H%M%S', time.localtime(time.time()))
# route
filePath = '{}\\{}_{}.png'.format(screenshot_path, model, dateNow)
try:
self.driver.save_screenshot(filePath)
self.logger.info(f" Screen capture successful , The picture path is {filePath}")
except:
self.logger.exception(' Screen capture failed !')
# sign out
def get_driver(self):
return self.driver
4. Page inheritance BasPage
from Common.basePage import BasePage
from selenium.webdriver.common.by import By
from time import sleep
class BaiduIndex(BasePage):
"""
Page elements
"""
# Baidu home page link
baidu_index_url = "https://www.baidu.com"
# Search box
search_input = (By.ID, "kw")
# " use Baidu Search " Button box
search_button = (By.ID, "su")
# Query operation
def search_key(self, search_key):
self.logger.info("【=== Search operations ===】")
# Wait for the user name text box element to appear
self.wait_eleVisible(self.search_input, model=' Search box ')
# Input content
self.input_text(self.search_input, " Atri ", model=" Search box ")
# Clear the contents of the text box
self.clean_inputText(self.search_input, model=' Search box ')
# enter one user name
self.input_text(self.search_input, text=search_key, model=' Search box ')
# Wait for the search button to appear
self.wait_eleVisible(self.search_button, model='" use Baidu Search " Search button ')
# Click the search button
self.click_element(self.search_button, model='" use Baidu Search " Search button ')
# After searching, wait for the interface to load
self.driver.implicitly_wait(10)
sleep(3)
5. pytest+allure Write test cases
notes :Pytest Integrate Allure Please refer to :https://www.cnblogs.com/huny/p/13752406.html
import os
import time
import pytest
import allure
from time import sleep
from selenium import webdriver
from PageObject.baiduIndex import BaiduIndex
driver = webdriver.Chrome()
baidu_index = BaiduIndex(driver)
@pytest.fixture(scope="class")
def init():
# Open the browser , Visit the login page
baidu_index.logger.info("\nWebDriver Initializing ...")
driver.get(baidu_index.baidu_index_url)
baidu_index.logger.info(f" Open the link : {baidu_index.baidu_index_url}...")
# window maximizing
driver.maximize_window()
# An implicit wait
driver.implicitly_wait(10)
baidu_index.logger.info("WebDriver Initialization complete !")
yield
driver.quit()
baidu_index.logger.info("WebDriver Quit successfully ...")
@allure.feature(" Baidu search ")
class TestBaiduSearch:
@allure.story(" Search for specified keywords ")
@pytest.mark.baidu_search
@pytest.mark.parametrize("key_word", [
" ha-ha ",
" ha-ha ",
], )
def test_search(self, init, key_word):
# @pytest.mark.parametrize A parameterized
baidu_index.search_key(key_word)
web_title = driver.title
assert " ha-ha _ Baidu search " == web_title
6. Generate Allure Test report
Github Address :https://github.com/Zimo6/Selenium_Demo
The following is the supporting information , For doing 【 software test 】 For our friends, it should be the most comprehensive and complete war preparation warehouse , This warehouse also accompanied me through the most difficult journey , I hope it can help you !
Last : It can be in the official account : Programmer Xiaohao ! Get a free copy of 216 Page software testing engineer interview guide document information . And the corresponding video learning tutorial is free to share !, It includes basic knowledge 、Linux necessary 、Shell、 The principles of the Internet 、Mysql database 、 Special topic of bag capturing tools 、 Interface testing tool 、 Test advanced -Python Programming 、Web automated testing 、APP automated testing 、 Interface automation testing 、 Testing advanced continuous integration 、 Test architecture development test framework 、 Performance testing 、 Safety test, etc. .
If my blog helps you 、 If you like my blog content , please “ give the thumbs-up ” “ Comment on ” “ Collection ” One button, three links ! Friends who like software testing , You can join our testing technology exchange group :779450660 There are various software testing resources and technical discussions )
边栏推荐
- leetcode-540. A single element in an ordered array
- Advanced collaboration: coroutinecontext
- Hcie security Day10: six experiments to understand VRRP and reliability
- From the behind the scenes arena of the ice and snow event, see how digital builders can ensure large-scale events
- Measurement fitting based on Halcon learning -- Practice [1]
- 电子科技大学|强化学习中有效利用的聚类经验回放
- 2022 melting welding and thermal cutting examination materials and free melting welding and thermal cutting examination questions
- Brief analysis of ref nerf
- Task of gradle learning
- 强基计划 数学相关书籍 推荐
猜你喜欢
Talk about daily newspaper design - how to write a daily newspaper and what is the use of a daily newspaper?
Borui data and Sina Finance released the 2021 credit card industry development report
MDM mass data synchronization test verification
Yyds dry goods inventory TCP & UDP
Qt6 QML Book/Qt Quick 3D/基础知识
XAI+网络安全?布兰登大学等最新《可解释人工智能在网络安全应用》综述,33页pdf阐述其现状、挑战、开放问题和未来方向
Viewing Chinese science and technology from the Winter Olympics (II): when snowmaking breakthrough is in progress
Battle drag method 1: moderately optimistic, build self-confidence (1)
Pengcheng cup Web_ WP
"Designer universe" APEC safety and health +: environmental protection Panda "xiaobaobao" Happy Valentine's Day 2022 | ChinaBrand | Asia Pacific Economic media
随机推荐
C 10 new feature [caller parameter expression] solves my confusion seven years ago
The 12th Blue Bridge Cup
Strange way of expressing integers (expanding Chinese remainder theorem)
淺析 Ref-NeRF
Kernel symbol table
Measurement fitting based on Halcon learning -- Practice [1]
Pengcheng cup Web_ WP
Phpexcel import export
Pytorch sets the weight and bias of the model to zero
Scientific research document management Zotero
Refer to some books for the distinction between blocking, non blocking and synchronous asynchronous
Recommendation of books related to strong foundation program mathematics
thrift go
Memory analyzer (MAT)
Transformer structure analysis and the principle of blocks in it
[secretly kill little buddy pytorch20 days -day02- example of image data modeling process]
MySQL master-slave synchronization principle
Shortest path problem of graph theory (acwing template)
Viewing Chinese science and technology from the Winter Olympics (II): when snowmaking breakthrough is in progress
[Yugong series] go teaching course 002 go language environment installation in July 2022