介绍
图片搜索是现在的多数浏览器都提供的功能,如果能用脚本实现一个自动化的检查,那么能够实现发版前的简单冒烟,或者日常的功能检查。
思路
针对PC网页端的浏览器的图片搜索功能进行编写脚本,
首先就是要确定用的语言框架及工具:Python+pytest+selenium,
其次是了解整个功能的流程:上传图片->开始搜索->结果验证,
最后搞清楚每个关键节点上会用到的相关组件或方法,开始coding。
难点及解决方式
1.对动态元素的定位
在做自动化的过程中,我喜欢先找到要操作的页面元素,然后根据其特性来决定定位方式。
如下,前四个都是能够很容易定位到的元素,title是搜索结果的文章页,是一个动态元素,这个时候需要借用到谷歌开发者工具来对其进行调试确定最后的定位路径,这里我用到了xpath提供的模糊匹配的方法contains()。
# 定义页面元素
img_search = "soutu-btn" # by class name
choose_img = "upload-pic" # by class name
search = "soutu-url-btn soutu-url-btn-new"
result_div = '//*[@id="app"]/div/div[2]/div/div[2]/div[3]/div/a' # by xpath
title = '//*[@id="ssr-content"]//div[starts-with(@class,"app-module")][2]//div[contains(@class,"index-module")]//div[contains(@class,"index-module")][1]' # xpath
guide = "graph-guide-info-btn" # class name
2.处理弹窗
多次尝试的过程中,发现搜索结果页会随机出现引导弹窗,类似下面这种,因为是随机出现的,所以在处理逻辑中要做判断,弹窗是否出现,出现就处理掉
3.如何对结果进行断言
对图片搜索结果进行断言,我首先想到了截图保留证据,这样也方便后期出问题验证。然后意识到,如果是做数据驱动,那是不是需要给上传的每个图片加个属性,来标识其内容特点,如猫,狗,人等。然后在断言的时候把结果内容与其进行比较。
所以我选择了搜索结果中的第一个结果来做点击操作,来获取其标题中的相关内容进行断言。
实现
import pytest
from selenium import webdriver
from selenium.common import TimeoutException
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from time import sleep, strftime, localtime, time
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
class TestSearchImg:
url = "https://www.baidu.com"
s = Service(executable_path=r'/Users/daisy/BrowserDrivers/chromedriver')
driver = webdriver.Chrome(service=s)
# 定义页面元素
img_search = "soutu-btn" # by class name
choose_img = "upload-pic" # by class name
search = "soutu-url-btn soutu-url-btn-new"
result_div = '//*[@id="app"]/div/div[2]/div/div[2]/div[3]/div/a' # by xpath
title = '//*[@id="ssr-content"]//div[starts-with(@class,"app-module")][2]//div[contains(@class,"index-module")]//div[contains(@class,"index-module")][1]' # xpath '//*[@id="ssr-content"]/div[2]/div/div[1]/div/div/div[1]'
guide = "graph-guide-info-btn" # class name
title_text = ''
def setup(self):
self.driver.get(self.url)
self.driver.fullscreen_window()
def teardown(self):
self.driver.quit()
def search_img(self):
self.driver.find_element(By.CLASS_NAME,self.img_search).click()
self.driver.find_element(By.CLASS_NAME,self.choose_img).send_keys("/Users/daisy/PycharmProjects/Test/PccwGlobal/part1/cat.png")
sleep(5)
# 获取当前窗口的句柄
origin_handle = self.driver.current_window_handle
# print("origin_handle",origin_handle)
file_name = "search-" + strftime("%Y%m%d-%H%M%S", localtime(time())) + ".png"
self.driver.save_screenshot(file_name)
# 处理引导弹窗
try:
ele = WebDriverWait(self.driver, 10, 0.5).until(lambda x: x.find_element(By.XPATH, self.result_div))
except TimeoutException:
if self.driver.find_element(By.CLASS_NAME,self.guide):
self.driver.find_element(By.CLASS_NAME, self.guide).click()
self.driver.execute_script("arguments[0].scrollIntoView();", ele)
self.driver.execute_script("arguments[0].click();", ele)
sleep(5)
# 跳到新窗口,获取所有句柄
handles = self.driver.window_handles
# print("All handles:", handles)
for i in handles:
if i != origin_handle:
self.driver.switch_to.window(i)
self.title_text = self.driver.find_element(By.XPATH,self.title).get_attribute('innerText')
# 截图
res_file_name = "result-" + strftime("%Y%m%d-%H%M%S", localtime(time())) + ".png"
self.driver.save_screenshot(res_file_name)
def test_search_img(self):
self.search_img()
assert '猫' in str(self.title_text)
if __name__ == '__main__':
pytest.main()
优化方向
1.用PO设计模式将代码整理得更易维护。
2.将处理弹窗的操作封装成为更通用的功能。
3.在大批量数据处理时,如何进行更通用的断言来判断结果的正确性。
我的断言只是简单的获取文章标题来判断其中是否有关键词,是很不通用的一种断言方式,当搜索结果中的第一结果变成了其他文章,我的这种方式就很容易失败,导致代码不够健壮。另外,如果在断言中用到一些图像处理/图像识别的方法,不知会不会是更有价值的解决方式。
以上是短时间内处理的一个小问题,所以目标是解决眼前的问题,各处都考虑不周,后期如果有时间还会继续优化,也欢迎小伙伴们来分享更好的解决方法。