您好!
欢迎来到京东云开发者社区
登录
首页
博文
课程
大赛
工具
用户中心
开源
首页
博文
课程
大赛
工具
开源
更多
用户中心
开发者社区
>
博文
>
测试角度看招采系统重构之自动化脚本录制
分享
打开微信扫码分享
点击前往QQ分享
点击前往微博分享
点击复制链接
测试角度看招采系统重构之自动化脚本录制
自猿其说Tech
2022-12-21
IP归属:未知
17280浏览
# 1 背景介绍 京东运输招采系统(以下简称招采系统)是运力八大产品-运力资源产品的核心系统之一,担负京东运输各业务条线(公路,铁路、航空、冷链、城配、B2B、大件宅配)的招采流程线上化及电子合同打通的支撑工作,为公司运力招采“降本增效”与“风险防范”提供有力保障。 招采系统集承运商入驻、运力资源管理、报价模版管理、招标书发布、承运商报价等功能于一体,打通承运商线上招标和管理。21年开始,招采系统经历大网与B2B业务融合、新增国际招采业务以及前后端分离改造,为保障招采黄金流程稳定运行且在较短时间内完成业务验证,故采用UI自动化方式实现黄金流程自动化,在引入或兼容其他业务时,即可通过UI自动化完成黄金链路验证。 # 2 内容介绍 京东运输招采系统当前融合公路,铁路、航空、冷链、城配、B2B、大件宅配等线上招采业务。随着招采业务丰富,和招采中台的建设思路,目前系统采用领域驱动设计思想(DDD)进行重新架构。作为测试同学的目标,就是在重构或改造后保证原有流程正常运行,避免重复操作,提高测试精准度,通过较小的开发成本完成UI自动化脚本更新迭代,完成功能验证,以下介绍通过Selenium IDE 进行UI自动化脚本录制,减少手工操作提高测试效率。 # 3 设计思路 Selenium IDE概念介绍 Selenium IDE最开始是嵌入浏览器的一个插件,通过这个插件可以简单的实现浏览器的录制与回放功能,就像一个记录操作步骤的机器人,在你需要的时候它可以按照记录的步骤重新执行一遍,这就是脚本录制。 选型介绍 目前团队使用的自动化框架基于pytest实现,支持API/UI用例的持续集成。招采系统采用Selenium IDE + Chrome浏览器的方式进行脚本录制,录制脚本通过一键导出python代码,结合现有自动化框架,通过录制+python轻代码实现UI用例,支持流程依赖、传参、断言等完整测试过程。 # 4 实践解读 ## 4.1 业务流程介绍 招采运营人员通过Bid系统进行标书创建并发布标书,之后具备承运能力的承运商按照自己的需求报名某些标的线路,并上传保证金凭证,保证金审核通过后承运商自动报名成功并进入报价阶段,承运商通过cloud系统进行报价,首轮报价排名前五的承运商进入议价阶段,后续进行议价和多次议价,议价截止后,排名前三的承运商入围,招采运营人员发布中标生成合同,完成整个标书流程 名词解释: Bid系统:用于某些线路定期招标承运商,发布标书、管理标书和合同 cloud系统:承运商使用的系统,用于承运商入驻、报名报价、管理车辆司机 招采:定期招标线路运输承运商的系统 承运商:京东招标的具备运输某些线路能力的车队或物流公司 自动化用例场景:实现一键创建标书、承运商报名、报价、议价,黄金流程的验证 ![](//img1.jcloudcs.com/developer.jdcloud.com/3078c9e5-00a7-4ccd-913f-dd732e33d15b20221220182933.png) ## 4.2 UI用例流程介绍 1.打开谷歌浏览器,安装Selenium IDE插件,访问如下地址完成插件安装,火狐也有该插件,但是录制缓慢,不推荐使用 https://chrome.google.com/webstore/detail/selenium-ide/mooikfkahbdckldjjndioackbalphokd ![](//img1.jcloudcs.com/developer.jdcloud.com/84ebd41d-9037-4052-a5d5-4c09801ca7a420221220182948.png) 2.安装完成后,在扩展程序中可以查到,开启允许访问文件地址,此操作目的为了满足界面上传文件时需求 ![](//img1.jcloudcs.com/developer.jdcloud.com/7ad8112f-3420-48c8-95af-30848e405b3620221220183018.png) 其中上传文件时:需要使用type方式进行上传,value=/Users/wangtong100/Desktop/测试资料/传摆合同/权重模板-体积计费零担.xls,具体如下截图 ![](//img1.jcloudcs.com/developer.jdcloud.com/79511960-e843-464b-8447-f036cc2a1e5320221220183317.png) 3.锁定插件在工具栏 ![](//img1.jcloudcs.com/developer.jdcloud.com/a98b64b0-1300-4a40-830d-91a0cfd432df20221220183036.png) 4.点击进入插件,创建新的录制项目 ![](//img1.jcloudcs.com/developer.jdcloud.com/433e5138-721e-4d00-b7b4-2e2031e6110b20221220183156.png) 创建项目名称 ![](//img1.jcloudcs.com/developer.jdcloud.com/ccee4e85-0458-4485-8782-0792abe4004220221220183213.png) 输入脚本录制域名,点击开始录制 ![](//img1.jcloudcs.com/developer.jdcloud.com/4d868d92-4a27-4564-9073-7e443838820520221220183227.png) 5.自动打开网址进行脚本录制,记录操作 ![](//img1.jcloudcs.com/developer.jdcloud.com/6354d1d4-abcb-472f-afeb-92b08671766c20221220183244.png) 所有操作均进行记录,包括点击、输入、上传文件等等 ![](//img1.jcloudcs.com/developer.jdcloud.com/b5c2a67b-af3d-4213-9612-edb972ab5f5b20221220183300.png) 6.生成的脚本支持编辑修改 支持修改定位方式 ![](//img1.jcloudcs.com/developer.jdcloud.com/608f72b8-82e0-4663-bec7-32679b2b17b920221220183339.png) 支持修改value值 ![](//img1.jcloudcs.com/developer.jdcloud.com/5ab4e689-6bfb-4c61-bc06-2e26d4dca8e320221220183358.png) 7.支持插入删除脚本以及各节点的操作 ![](//img1.jcloudcs.com/developer.jdcloud.com/e4d34169-75b0-4ca8-b2a0-ae3492b84e7b20221220183429.png) 8.支持调整脚本运行速度 ![](//img1.jcloudcs.com/developer.jdcloud.com/490759f6-cb68-4b2d-8ad0-323a528182c020221220183448.png) 9.支持assert\verify方式进行断言 ![](//img1.jcloudcs.com/developer.jdcloud.com/bcf76e3f-1de9-4445-8c15-a5926d7af06720221220183509.png) ![](//img1.jcloudcs.com/developer.jdcloud.com/ecf98d54-b8a8-4658-b139-4d03b1e463aa20221220183522.png) 10.脚本录制可以随时开始和结束 ![](//img1.jcloudcs.com/developer.jdcloud.com/9cd8291f-803e-4acd-b243-01275497bcf720221220183541.png) 11.脚本支持导出成不同语言的脚本,其中包括python语言 ![](//img1.jcloudcs.com/developer.jdcloud.com/e9a2a606-7bb0-4e0b-a65a-b907e838b13320221220183601.png) ![](//img1.jcloudcs.com/developer.jdcloud.com/e4a9ac76-9d67-40df-ab05-d1ce23ab691820221220183614.png) 导出脚本如下:可在pycharm中运行 ``` # Generated by Selenium IDE import pytest import time import json from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.support import expected_conditions from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.desired_capabilities import DesiredCapabilities class Test1(): def setup_method(self, method): self.driver = webdriver.Chrome() self.vars = {} def teardown_method(self, method): self.driver.quit() def wait_for_window(self, timeout = 2): time.sleep(round(timeout / 1000)) wh_now = self.driver.window_handles wh_then = self.vars["window_handles"] if len(wh_now) > len(wh_then): return set(wh_now).difference(set(wh_then)).pop() def test_1(self): self.driver.get("http://tms-bid.test.jd.com") self.driver.set_window_size(1558, 969) self.driver.find_element(By.ID, "username").click() self.driver.find_element(By.ID, "username").send_keys("dbsxw") self.driver.find_element(By.ID, "password").click() self.driver.find_element(By.ID, "password").send_keys("xinxibu456") self.driver.find_element(By.ID, "formsubmitButton").click() self.driver.find_element(By.LINK_TEXT, "招标书管理").click() self.driver.switch_to.frame(0) self.driver.find_element(By.ID, "createButton").click() time.sleep(2) self.driver.find_element(By.CSS_SELECTOR, ".confirm").click() self.driver.find_element(By.ID, "judgesNum").click() self.driver.find_element(By.ID, "judgesNum").send_keys("1") value = self.driver.find_element(By.ID, "judgesNum").get_attribute("value") assert value == "1" self.driver.find_element(By.ID, "bidBookName").click() self.driver.find_element(By.ID, "bidBookName").send_keys("招采全流程测试") self.driver.find_element(By.ID, "entryEndTime").send_keys("2022-02-25 10:08:20") self.driver.find_element(By.ID, "quotationEndTime").send_keys("2022-02-25 10:13:20") self.driver.find_element(By.ID, "businessEndTime").send_keys("2022-02-25 10:18:20") self.driver.find_element(By.ID, "discussionEndTime").send_keys("2022-02-25 10:23:20") self.driver.find_element(By.ID, "bidDocumentFile").click() self.driver.find_element(By.ID, "bidDocumentFile").send_keys("/Users/wangtong100/Desktop/测试资料/传摆合同/权重模板-体积计费零担.xls") self.driver.find_element(By.ID, "contacterName").send_keys("lhy") value = self.driver.find_element(By.ID, "contacterName").get_attribute("value") assert value == "lhy" self.driver.find_element(By.ID, "contacterMobile").send_keys("13212341234") value = self.driver.find_element(By.ID, "contacterMobile").get_attribute("value") assert value == "13212341234" self.driver.find_element(By.ID, "contacterEmail").send_keys("1205675380@qq.com") value = self.driver.find_element(By.ID, "contacterEmail").get_attribute("value") assert value == "1205675380@qq.com" self.driver.find_element(By.ID, "nextBtn").click() self.driver.find_element(By.ID, "businessType").click() dropdown = self.driver.find_element(By.ID, "businessType") dropdown.find_element(By.XPATH, "//option[. = '普货']").click() self.driver.find_element(By.ID, "transType").click() dropdown = self.driver.find_element(By.ID, "transType") dropdown.find_element(By.XPATH, "//option[. = '传站']").click() self.driver.find_element(By.ID, "serviceIndustryLevelOne").click() dropdown = self.driver.find_element(By.ID, "serviceIndustryLevelOne") dropdown.find_element(By.XPATH, "//option[. = '快销']").click() self.driver.find_element(By.ID, "bidTemplateName").click() self.driver.find_element(By.LINK_TEXT, "体积计费零担").click() self.driver.find_element(By.ID, "importFile").click() self.driver.find_element(By.ID, "importFile").send_keys("/Users/wangtong100/Desktop/测试资料/传摆合同/权重模板-体积计费零担.xls") self.driver.find_element(By.ID, "priceKind").click() self.driver.find_element(By.ID, "priceKind").send_keys("90") self.driver.find_element(By.ID, "businessKind").send_keys("10") self.driver.find_element(By.ID, "classifyCode").click() dropdown = self.driver.find_element(By.ID, "classifyCode") dropdown.find_element(By.XPATH, "//option[. = '是否一般纳税人']").click() self.driver.find_element(By.CSS_SELECTOR, "#btnBusinessAdd > .icon-plus").click() element = self.driver.find_element(By.CSS_SELECTOR, "#btnBusinessAdd > .icon-plus") actions = ActionChains(self.driver) actions.move_to_element(element).perform() element = self.driver.find_element(By.CSS_SELECTOR, "body") actions = ActionChains(self.driver) actions.move_to_element(element, 0, 0).perform() self.driver.find_element(By.ID, "1").click() self.driver.find_element(By.ID, "1").send_keys("10") self.driver.find_element(By.ID, "earnestMoney").click() self.driver.find_element(By.ID, "earnestMoney").send_keys("123") self.driver.find_element(By.ID, "nextBtn").click() self.driver.find_element(By.ID, "finishBtn").click() self.driver.find_element(By.CSS_SELECTOR, "tr:nth-child(1) > td:nth-child(1) .btn-primary").click() time.sleep(0.5) self.driver.find_element(By.CSS_SELECTOR, ".confirm").click() self.driver.find_element(By.CSS_SELECTOR, ".confirm").click() ``` 12.脚本录制后运行结果展示 失败结果 ![](//img1.jcloudcs.com/developer.jdcloud.com/852dbeb1-cd1f-4f0c-9452-b1d1f56033ce20221220183700.png) 通过结果 ![](//img1.jcloudcs.com/developer.jdcloud.com/02b523cc-c023-4093-abe4-f81f208c37c120221220183717.png) 13.保存文件,生成side文件,可以在插件中直接打开 ![](//img1.jcloudcs.com/developer.jdcloud.com/d7c42b0a-1701-4a1f-af1f-450f451bccc520221220183745.png) ![](//img1.jcloudcs.com/developer.jdcloud.com/de718184-a4b8-47f5-a94f-374f4f1d8dd720221220183756.png) # 5 总结 Selenium IDE 是一款可以在日常功能测试中即可录制的工具,只要很好的加以利用就可以提升测试效率和质量 当然以上还有许多不足之处,欢迎大家一起探讨研究 ------------ 自猿其说Tech-JDL京东物流技术与数据智能部 **作者:王通**
原创文章,需联系作者,授权转载
上一篇:自营车专项-自营车排班能力建设思路
下一篇:TiDB 底层存储结构 LSM 树原理介绍
自猿其说Tech
文章数
426
阅读量
2149963
作者其他文章
01
深入JDK中的Optional
本文将从Optional所解决的问题开始,逐层解剖,由浅入深,文中会出现Optioanl方法之间的对比,实践,误用情况分析,优缺点等。与大家一起,对这项Java8中的新特性,进行理解和深入。
01
Taro小程序跨端开发入门实战
为了让小程序开发更简单,更高效,我们采用 Taro 作为首选框架,我们将使用 Taro 的实践经验整理了出来,主要内容围绕着什么是 Taro,为什么用 Taro,以及 Taro 如何使用(正确使用的姿势),还有 Taro 背后的一些设计思想来进行展开,让大家能够对 Taro 有个完整的认识。
01
Flutter For Web实践
Flutter For Web 已经发布一年多时间,它的发布意味着我们可以真正地使用一套代码、一套资源部署整个大前端系统(包括:iOS、Android、Web)。渠道研发组经过一段时间的探索,使用Flutter For Web技术开发了移动端可视化编程平台—Flutter乐高,在这里希望和大家分享下使用Flutter For Web实践过程和踩坑实践
01
配运基础数据缓存瘦身实践
在基础数据的常规能力当中,数据的存取是最基础也是最重要的能力,为了整体提高数据的读取能力,缓存技术在基础数据的场景中得到了广泛的使用,下面会重点展示一下配运组近期针对数据缓存做的瘦身实践。
自猿其说Tech
文章数
426
阅读量
2149963
作者其他文章
01
深入JDK中的Optional
01
Taro小程序跨端开发入门实战
01
Flutter For Web实践
01
配运基础数据缓存瘦身实践
添加企业微信
获取1V1专业服务
扫码关注
京东云开发者公众号