使用Selenium与Unittest搭建UI自动化测试用例四层架构

本人在学习搭建UI自动化架构时,发现网上讲解的搭建过程不是很详细。便写下该篇文章,便于记录及后续本人与读者使用。

开源地址

Gitee:Selenium+Unittest测试UI自动化框架

四层目录

Base(基本动作层)
Case(用例层)
Data(数据层)
Page(业务层)
在这里插入图片描述

Base基本动作层

该层用于存放UI基本操作步骤,例:点击、输入、按键
action.py(里面有我常用的基本动作含动作用法注释,欢迎大家评论区补充)

import time
from selenium import webdriver
from selenium.webdriver import ActionChains, Keys
from selenium.webdriver.common.by import By

class Bases:
	 # driver = webdriver.Chrome()
	 def __init__(self, driver):
	  self.driver = driver
	
	 # OpenChrome打开浏览器
	 def open(self, url):
	  self.driver.get(url)
	  self.driver.maximize_window()
	  self.wait(10)
	
	 # 打开新标签页
	 def open_new(self):
	  self.driver.switch_to.new_window('tab')
	
	 # 获取当前窗口页面的窗口句柄
	 def NewHandles(self):
	  time.sleep(3)
	  first_window = self.driver.current_window_handle[0]
	  new_window = self.driver.current_window_handle
	  print('旧页面:' + first_window + ';切换定位新页面:' + new_window)
	  time.sleep(2)
	
	 # Find Element寻找元素定位
	 def local(self, sid, value):
	  self.wait(10)
	  return self.driver.find_element(sid, value)
	
	 # Click Element点击元素定位
	 def click(self, sid, value):
	  self.local(sid, value).click()
	  print('点击元素:' + value)
	
	 # 双击元素定位
	 def double_click(self, sid, value):
	  ActionChains(self.driver).double_click(self.local(sid, value)).perform()
	  print('双击元素:' + value)
	
	 # Input Element输入元素定位
	 def input(self, sid, value, txt):
	  b = self.local(sid, value)
	  # 清除只读属性
	  self.driver.execute_script('arguments[0].removeAttribute(\"readonly\")', b)
	  b.clear()
	  b.send_keys(txt)
	  print('元素:' + value + ',输入:' + txt)
	
	 # edit web excel编辑表格
	 def edit(self, sid, value, txt):
	  self.local(sid, value)
	  time.sleep(1)
	  ActionChains(self.driver).send_keys(txt).perform()
	  print('元素:' + value + ',输入:' + txt)
	
	 # imitate keyboard键盘操作
	 def KeyBoard(self, sid, value, keys):
	  self.local(sid, value).send_keys(keys)
	  print('元素:' + value + ',键盘操作:' + keys)
	
	 # find txt in page寻找指定文本是否在页面
	 def wait_page(self, txt):
	  time.sleep(2)
	  if txt in self.driver.page_source:
	   print(txt + ',等待5秒后再操作')
	   time.sleep(5)
	  else:
	   print('检测不到:' + txt + ',自动化继续操作')
	
	 # choice to pull down下拉框内容下移与回车
	 def PullOption(self, sid, value):
	  self.KeyBoard(sid, value, Keys.DOWN)
	  self.KeyBoard(sid, value, Keys.ENTER)
	
	 # pull to input text下拉框输入内容下移与回车
	 def PullToInput(self, sid, value, txt):
	  self.input(sid, value, txt)
	  self.PullOption(sid, value)
	
	 # Wait Element等待元素
	 def wait(self, times):
	  return self.driver.implicitly_wait(times)
	
	 # 跳转上个页面
	 def LastPage(self):
	  self.driver.switch_to.window(self.driver.window_handles[0])
	
	 # QuitChrome关闭浏览器
	 def quit(self):
	  self.driver.quit()

Case用例层

该层存放自动化用例并用于执行
Testcase.py(setUpClass初始化类级别的资源和环境,tearDownClass测试方法执行完毕后自动执行一些清理操作,test01登录操作,test02用例执行)

注:每新增一个用例得在setUpClass定义 如cls.t03 = test031(cls.driver)

import unittest

from ddt import ddt, file_data
from selenium import webdriver

from Page.Login import Login
from Page.test01 import test011


@ddt
class ContractCase(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        cls.driver = webdriver.Chrome()
        cls.driver.maximize_window()
        cls.lg = Login(cls.driver)
        cls.sc = test011(cls.driver)

    @classmethod
    def tearDownClass(cls) -> None:
        pass

    def test01(self):
        self.lg.login55()

    @file_data("../Data/test01.yaml")
    def test02(self, Number):
        self.sc.test0111(Number)

Data数据层

该层用于存储业务层数据变量,方便后续维护与调整。如:数据不适用能更快速找到位置更改

注:一个用例配一个yaml
test01.yaml

-
   Number: 0001

Page业务层

该层用于编写业务操作步骤,用于Testcase调用。

Login.py(登录单独写出公用方法,便于后续不同Testcase统一调用,增强代码的简洁性与实用性)

import time
  from selenium.webdriver.common.by import By
  from Base.action import Bases

  class Login(Bases):
   # 登录环境链接
   Url55 = 'https://test.kritycat.com'
   Url81 = 'https://uat.kritycat.com'
   # 登录账号与密码
   user = ''
   password = ''

   # 登录55环境
   def login55(self):
    # 打开环境链接
    self.open(self.Url55)
    # 登录操作引用
    self.LoginKeyBoard()
    time.sleep(5)

   # 登录81环境
   def login81(self):
    # 打开环境链接
    self.open(self.Url81)
    # 登录操作引用
    self.LoginKeyBoard()
    time.sleep(5)

   # 登录操作
   def LoginKeyBoard(self):
    # 账号
    self.input(By.ID, 'user', self.user)
    # 密码
    self.input(By.ID, 'password', self.password)
    # 点击登录
    self.click(By.ID, 'login')

test01.py(用例01业务操作步骤)

from selenium.webdriver.common.by import By

from Base.action import Bases


class test011(Bases):
    def test0111(self, Number):
        # 业务步骤
        self.click(By.ID, "Type")
        self.input(By.XPATH, '//*[@id="Type"]/div/div/input', Number)

附分层意义的解答:

分层的目的用于代码可维护性,可行性,可持续性,简洁性。下面我列举几个例子,大家就会知道分层的意义。

例:四个层级合并在一个用例写,当登录环境地址切换 你需每个用例都调整,分层只需调整Login.py

四个层级合并在一个用例写,当变量数据全部需要调整时,你得找到每个步骤修改数据,分层只需调整test02.yaml

  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KrityCat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值