Selenium 写的自动化脚本(UI,接口)

testjson · 2022年09月29日 · 最后由 风子 回复于 2022年10月12日 · 9738 次阅读

这是我写的 web ui 自动化脚本


UI 自动化脚本已经部署到了 jenkins

这个是接口自动化的脚本,接口自动化目前还没有往 jenkins 部署

我就是想知道,我这跟公司真实的自动化还缺了那些东西,或者说我写的哪里不对?
以后的计划是把框架进行封装,写自动化测试平台

最佳回复

资料有点少,不好评价反馈,只能留点疑问,楼主可以看下有没有做好:
1、UI 自动化里面,框架是否有提供什么机制便于提高用例稳定性?(如找元素的自动等待等)
2、UI 自动化脚本的写法里,怎么尽可能让代码容易复用?(如 PageObject,从代码看有 Page 的概念,但不确定是不是用了 PO 模式)
3、一旦有报错,框架层是否可以捕获并输出足够清晰的日志等信息,便于使用者基于日志就可以定位并解决问题?

接口自动化:
1、一般接口自动化的特点是数量多,如果每一个都得写不少代码的话,编写维护成本会相对高。针对这块是否有评估过一个接口用例按现在框架写,大概要多久?
2、从这个截图看,有不少代码是为把报告输出到 allure 服务的。不确定这部分是不是用例,如果是,可以考虑下把这部分由框架直接代劳,而不用每个用例自己写?
3、类似 UI 自动化,接口自动化也有流程型的用例的,通过调用多个接口形成一个流程进行测试。不知道是否有考虑过脚本如何分层,让流程型用例和单接口用例,都能尽量复用一些公共代码,降低编写成本?
4、接口测试很多时候会需要测试多个环境,从脚本看像是从一个全局配置文件里直接获取 url 的,建议框架可以提供多环境分开配置的能力(类似 spring 里面可以分别为 dev 和 prod 设定不同的配置项对应值)。

共收到 27 条回复 时间 点赞

最近在研究这方面的东西,就是想知道,我写的这个跟真实的公司做自动化差别在哪里?

资料有点少,不好评价反馈,只能留点疑问,楼主可以看下有没有做好:
1、UI 自动化里面,框架是否有提供什么机制便于提高用例稳定性?(如找元素的自动等待等)
2、UI 自动化脚本的写法里,怎么尽可能让代码容易复用?(如 PageObject,从代码看有 Page 的概念,但不确定是不是用了 PO 模式)
3、一旦有报错,框架层是否可以捕获并输出足够清晰的日志等信息,便于使用者基于日志就可以定位并解决问题?

接口自动化:
1、一般接口自动化的特点是数量多,如果每一个都得写不少代码的话,编写维护成本会相对高。针对这块是否有评估过一个接口用例按现在框架写,大概要多久?
2、从这个截图看,有不少代码是为把报告输出到 allure 服务的。不确定这部分是不是用例,如果是,可以考虑下把这部分由框架直接代劳,而不用每个用例自己写?
3、类似 UI 自动化,接口自动化也有流程型的用例的,通过调用多个接口形成一个流程进行测试。不知道是否有考虑过脚本如何分层,让流程型用例和单接口用例,都能尽量复用一些公共代码,降低编写成本?
4、接口测试很多时候会需要测试多个环境,从脚本看像是从一个全局配置文件里直接获取 url 的,建议框架可以提供多环境分开配置的能力(类似 spring 里面可以分别为 dev 和 prod 设定不同的配置项对应值)。

去看 poium 和 seldom 项目,github 自己找,那是落地的工程类项目,不是 kpi 项目

脚本距离框架还有很长的路要走,要想做一个团队都能用的框架,至少要解决几个问题:1
1、用例去脚本化,比如 Excel、json 维护用例
2、入参数据解决,比如数据库依赖、接口依赖
3、断言问题与问题 2 类似
4、登录、加解密、验证码等项目非通用性问题
5、报告输出,不能光有简单的执行结果,还要统计接口数、覆盖率等更丰富的数据展示维度
共勉

5楼 已删除
陈恒捷 回复

看了,你的回复,我先修改下 ui 自动化的测试框架,UI 的问题,你说的 1,2,3, 2 和 3 有做,但是还是有问题,1 我用的隐式等待和强制等待,觉得不太好,打算改



陈恒捷 回复

https://blog.csdn.net/dream_back/article/details/118751500
我找了一篇博客,看了别人封装的 po,觉得我现在的 po 有很大问题,定位元素的部分太过繁琐,而且还把业务的测试流程放在 page 里了

陈恒捷 回复


这是在测试用例里面的加的 log 日志,断言,用例成功后的截图

页面就是页面 动作就是动作 页面只维护元素对象 动作单独抽象出来 不建议写在页面对象里
写用例时再把元素和动作组合起来

fiskeryang 回复

嗯,我设计的确实这块问题很大,已经在重构了,打算封装一个基类 basepage 把启动浏览器,元素定位的类型,操作等单独封装起来

testjson 回复

页面基类只维护页面公共元素 动作另外封装

fiskeryang 回复

一些常用的输入,点击,可以封装在基类页面吗

楼主,代码可以贴代码。markdown 的代码块。别截图。

恒温 回复

好的

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

class Page():
    def __init__(self):
        self.driver = webdriver.Chrome()
    def open(self):
        self.driver.get("https://www.baidu.com")
        self.driver.maximize_window()

    def __find_element__(self, lc, locator):
        """元素定位"""
        if lc == "id":
            ele = self.driver.find_element(By.ID, locator)
            print(type(ele))
            WebDriverWait(self.driver, 10).until(ec.visibility_of_element_located(ele))
a=Page()
a.open()
a.__find_element__('id','kw').send_keys('python')

我打算重构的 basepage 页,简单调试了下,报了这个错

<class 'selenium.webdriver.remote.webelement.WebElement'>
Traceback (most recent call last):
  File "D:/demo_123/basic/page.py", line 48, in <module>
    a.__find_element__('id','kw').send_keys('python')
  File "D:/demo_123/basic/page.py", line 19, in __find_element__
    WebDriverWait(self.driver, 10).until(ec.visibility_of_element_located((ele)))
  File "D:\demo_123\venv\lib\site-packages\selenium\webdriver\support\wait.py", line 81, in until
    value = method(self._driver)
  File "D:\demo_123\venv\lib\site-packages\selenium\webdriver\support\expected_conditions.py", line 125, in _predicate
    return _element_if_visible(driver.find_element(*locator))
TypeError: find_element() argument after * must be an iterable, not WebElement
testjson 回复

可以参考下 RF 的设计 ,动作就是动作 元素就是元素

执行用例时 就是元素 + 动作 来完成一次操作 比如

1、用户名元素 + 输入 (参数)
2、密码元素 + 输入(参数)
3、登录按钮元素 + 左键点击

打个比方
类似于 selenium 本身也封装了 click 方法

你可以再封装一层 把 driver.click + Action 类的 Click + JavaScript 的 Click 封装到一起 做成自定义的动作 myClick 简化脚本开发的操作

元素的定位方式和用例数据可以单独抽离出来,实现脚本与数据分离

孤千羽 回复

嗯是这样的

fiskeryang 回复
def find_element(self, lc, locator,timeout=''):
    """元素定位"""
    if lc == "xpath":
        ele = WebDriverWait(self.driver, timeout=10)\
            .until(EC.visibility_of_element_located((By.XPATH,locator)))
class Login_Page_Locator(BasePage):
    """登录页元素定位"""
    username = ('xpath', '//input[@placeholder="请输入用户名"]')
    password = ('xpath', '//input[@placeholder="请输入密码"]')
    submit = ('xpath','//span[text()="登录"]')
class Test_Login(object):
    loginpage = Login_Page_Locator()
    base = BasePage()
    @allure.story("登录用例")
    @allure.severity(allure.severity_level.BLOCKER)
    def test_login1_normal(self):
        """username and passwd is normal"""
        Logger().info('test_login success')
        try:
            #输入用户名
            self.base.find_element(self.loginpage.username[0],self.loginpage.username[1]).send_keys(username)
        except NoSuchElementException:
            Logger().error('login no find element')
        #assert username == "admin"
        #insert_img("login_normal.png")

为什么我这样写,一直在定位元素

好了,已经解决了上面的问题了,但是不知道为什么会启动两次浏览器,我再看看

fiskeryang 回复

还有,帮我看下,我这样写有啥问题吗,我现在感觉这样写,测试用例里面,取定位元素的方式,和值,那块有点繁琐,不知道能不能再优化

base.find_element(loginpage.username[0],loginpage.username[1]).send_keys(username)

就这一块

testjson 回复

确实比较繁琐 其实现在的前端响应式框架 基本都得靠 xpath 来定位元素了 所以你可以给个默认值为 xpath 可以省一个参数 另外定位元素的方法还需要多扩展几个 至少要覆盖常用的显示等待预定义条件以及自定义条件的场景

其实如果你是想要做框架的话 最好能让脚本能脱离代码环境 能通过编辑配置文件来编写用例脚本

fiskeryang 回复

嗯,元素定位的方法我写了很多,什么 id,name,等,粘贴的代码只粘贴了一个 xpath 的,确实,我写的时候好多定位都是 xpath, 你说的让脚本脱离代码环境,是说的数据驱动,关键字驱动吗,这个我有考虑做,后面计划是想做成这样

testjson 回复

1、默认为 xpath 如果不是再传可选参数
2、是这个意思 在代码里定义规则和 Api 通过配置文件来实现业务脚本

fiskeryang 回复

好的,我再继续把我的框架优化下

推荐你看看教程
https://coding.imooc.com/class/592.html
一整套 ui 自动化测试流程落地

陈恒捷 回复

捷哥,好厉害

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册