当前位置:   article > 正文

【软件测试】总结web自动化测试-selenium+python_webui自动化测试总结

webui自动化测试总结

自动化测试指软件测试的自动化,在预设状态下运行应用程序或者系统,预设条件包括正常和异常,最后评估运行结果。将人为驱动的测试行为转化为机器执行的过程。
常见的自动化测试工具:QTP、selenium、Rational Robot 、jmeter、appium、soapui、Loadrunner等等
selenium 是一个web 的自动化测试工具,不少学习功能自动化的同学开始首选selenium , 相因为它相比QTP 有诸多有点:

  • 多平台:windows、linux、MAC 。
  • 支持多浏览器:ie、Firefox、safari、opera、chrome。
  • 支持分布式测试用例的执行,可以把测试用例分布到不同的测试机器执行,相当于分发机的功能

文章目录

一、使用selenium IDE录制测试脚本

selenium IDE,可以安装到浏览器的插件上,Microsoft Edge浏览器中,可以不用翻墙,就能安装IDE,而像Chrome浏览器,好像要翻出去才能安装。这里就不细说Chrome怎么装了,以下是Edge浏览器的安装流程。

  • 打开Edge浏览器的扩展

    image-20220121150223963

  • 打开Edge的插件商店

    image-20220121150342426

  • 安装插件

    image-20220121150445430

安装成功后,在“地址栏”的右边就会出现图标,又或者点击扩展就能看到。

image-20220121150713408

录制脚本过程如下

  1. 打开IDE后,点击第一行蓝色字体;

    image-20220121150930408

  2. 输入工程名

    image-20220121151113002

  3. 输入被测试的网址

    image-20220121151147431

  4. 点击 “START RECORDING”后,会打开浏览器,并且进入到被测试的网站里

    image-20220121151326656

  5. 进入测试操作,比如输入“彭于晏”。然后鼠标点击IDE的停止按钮,脚本就录制好了。

    image-20220121151506787

  6. 输入这次测试的名称

    image-20220121151537759

  7. 运行录制的脚本

    image-20220121151651706

  8. 导出录制的脚本

    image-20220121152146568

以上就是用selenium IDE,进行录制脚本,并且将录制的脚本转换为编程语言,例如Python。

二、Python+selenium 环境搭建

1、Python+selenium

我自己安装的Python3.10版本,编译环境用的是pycharm。

在安装Python解释器的时候,直接用默认安装路径即可,如下,是我的安装路径:

image-20220121152814384

pycharm的配置

  1. image-20220121153153001

    image-20220121153248864

  2. 然后安装selenium包

    image-20220121153327410

    image-20220121153414372

上诉是在pycharm上安装selenium包,有的人可能安装不上,那么可以试试在cmd命令行窗口试试这条命令:

pip install selenium // 用于安装selenium
pip show selenium //用于查看是否已经安装selenium
  • 1
  • 2

安装好后,就是这样的

image-20220121153735630

2、webdriver

selenium安装好之后,就只差一个浏览器驱动了。不同的浏览器,不同的版本,驱动是不一样的。Chrome浏览器,国内有镜像源

可以在这里找到Chrome的驱动。Edge浏览器,好像不用翻墙也能够下载到。

在下载驱动的时候,驱动的版本号要和浏览器的版本号对应上,有可能你安装的浏览器的版本号,找不到相应的驱动。安装临近的驱动版本号也是可以的。如图:

image-20220121154841578

将下载好的驱动,解压到Python解释器的安装路径下(Script文件夹),如下:

image-20220121155117804

至此,环境就搭建好了。

三、selenium下,webdriver的常用API

在讲解API时,我们首先要知道selenium需要导包的,如下:

from selenium import webdriver
# webdriver 就是浏览器的驱动,用这个驱动,能完成很多浏览器的操作
driver = webdriver.Edge() # 获取Edge浏览器的驱动
driver.get("https://www.baidu.com/") # 让浏览器打开百度搜索
  • 1
  • 2
  • 3
  • 4

1、定位元素

在打开百度搜索之后,我们需要定位到“搜索框”,然后才能进行输入。那么如何定位到搜索框呢?我们有以下几种方法:

1)、id 和name

id 和name 是我们最最常用的定位方式,因为大多数控件都有这两个属性,而且在对控件的id 和name 命名时一般使其有意义也会取不同的名字。通过这两个属性使我们找一个页面上的属性变得相当容易。

在浏览器中,打开开发者工具(按F12)。就能查看到页面的每一个元素的前端代码。

image-20220121160418900

# 在上文中,已经打开获得浏览器驱动的情况下,输入以下代码就能定位元素
driver.find_element_by_id("kw") # 通过id定位
driver.find_element_by_name("wd") # 通过name定位
  • 1
  • 2
  • 3

2)、tag name 和 class name

image-20220121160931812

看上图,知道搜索框的标签是“input”,并且class=“s_ipt”。那么我们也可以通过这两个属性进行定位。但是需要知道的是,使用tag name 进行定位,可能得到的不止一个标签的数据。所以在使用的时候,需要注意页面共有多少个相同的标签。

driver.find_element_by_tag_name("input") # 得到所有的input标签
driver.find_element_by_class_name("s_ipt") # 得到class="s_ipt"的元素
  • 1
  • 2

3)、CSS_selector 定位

image-20220121162818329

driver.find_element_by_css_selector("#kw") # 通过Css_selector定位
  • 1

4)、Xpath定位

image-20220121162904045

上图两个都行

driver.find_element_by_xpath("//*[@id="kw"]") # 通过xpath进行定位
  • 1

5)、link text

有的时候,页面不是搜索框之类的,而是一条链接,也就是HTML中的a标签,此时就可以link text进行定位,值得注意的是,这种定位,输入的参数,也就是这条链接的名称,在当前页面只能是唯一的。只有这样,才能通过link进行定位。

image-20220121163816996

driver.find_element_by_link_text("新闻").click() # 通过link text进行定位,并且点击
  • 1

6)、partial link text

根据名称都知道,这就是link text的模糊查询。如下:

driver.find_element_by_partial_link_text("闻").click() # 通过partial_link text进行定位,并且点击
  • 1

只通过一个“闻“字,就能够定位到”新闻“.

2、操作测试对象

前面讲了很多的定位元素的操作,那么定位到元素之后,又有如下这些操作;

  • click() 点击操作

  • send_keys() 输入参数

  • clear() 清空当前输入框

  • submit() 提交表单

  • text 没有括号,这里的获取元素的文本信息

    from selenium import webdriver
    import time

    driver = webdriver.Edge()
    driver.get(“https://www.baidu.com/”)

    driver.find_element_by_id(“kw”).send_keys(“彭于晏”) # 搜索框 输入彭于晏
    driver.find_element_by_id(“su”).click() # 点击 百度一下
    time.sleep(2) # 停留2秒
    driver.find_element_by_id(“kw”).clear() # 清空搜索框的内容
    driver.find_element_by_id(“kw”).send_keys(“胡歌”) # 搜索框输入胡歌
    driver.find_element_by_id(“su”).click() # 点击 百度一下
    time.sleep(2)

    driver.quit() # 关闭浏览器

以上就是一份完整的代码,先是搜索了彭于晏,然后清空输入框,再搜索胡歌。

3、添加等待

在上面的代码中,可能你已经看到了time.sleep(),这就是等待。这个time,是需要导入time包的。除了这个,还有一个等待的函数

driver.implicitly_wait(5) # 智能等待
  • 1

括号里面填的是最长等待时间,单位秒。

这个方法呢,可以在这样的场景下使用:

image-20220121170543870

在搜索出结果后,需要点击百度百科,查看详细信息。因为在点击搜索彭于晏的时候,浏览器需要向后台发送请求,只能后台给出回应之后,才能看到这“百度百科”这几个字,这个时候才能点击。所以在点击百度百科的时候,是需要等待后台响应的,这段时间,人们是不能把控的,就可以通过智能等待,这个函数。

上诉代码的意思就是,在5秒之内,“百度百科”这几个字出来之后,就直接点击了。不需要傻傻的等待5秒。那么如果5秒后,还没点击的haul,就会报出异常。

from selenium import webdriver
import time

driver = webdriver.Edge()
driver.get("https://www.baidu.com/")
driver.find_element_by_id("kw").send_keys("彭于晏") # 搜索框 输入彭于晏
driver.find_element_by_id("su").click() # 点击 百度一下

driver.implicitly_wait(5) # 智能等待

driver.find_element_by_link_text("百度百科").click() # 点击 百度百科,查看详情
time.sleep(2)

driver.quit()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

4、打印信息

可能通过一些函数,查看当前网页的URL和title的信息,如下

from selenium import webdriver
import time

driver = webdriver.Edge()
driver.get("https://www.baidu.com/")
print(driver.title) # 打印title
print(driver.current_url) # 打印URL

driver.quit()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

image-20220121171717266

5、浏览器的相关操作

浏览器窗口的最大化和最小化:

driver.maximize_window() # 最大化
driver.minimize_window() # 最小化
  • 1
  • 2

除了最大化最小化,我们还可以手动的设置窗口的长宽。

driver.set_window_size(480, 800) # 长480,宽800
  • 1

浏览器的后退和前进,也就是浏览器左上角的两个箭头。

image-20220121173300676

driver.back() # 后退
driver.forward() # 前进
  • 1
  • 2

控制网页的滚动条。python是做不到这个操作的,只能通过javaScript的语句,来达到。

js = "var q=document.documentElement.scrollTop=10000" # 这里设置为10000,表示滚动条拉到最下面
driver.execute_script(js) # 执行上面的JavaScript语句
  • 1
  • 2

scrollTop 设置为10000,表示滚动条拉到最下面。相反的,设置为0,就表示将滚动条拉到最上面。execute_script(script, *args),在当前窗口/框架同步执行javaScript 。

6、键盘事件

在有些场景,我们是需要使用键盘的,我们也是可以通过驱动,来按动键盘,也可以使用组合键,比如Ctrl + C等等。

# 首先是需要进行导包的
from selenium.webdriver.common.keys import Keys
# 通过send_Keys(),来按键
send_Keys(Keys.TAB) # tab键
send_Keys(Keys.ENTER) # 回车键
# 组合键的用法
send_Keys(Keys.CONTROL, 'a') # Ctrl + a
send_Keys(Keys.CONTROL, 'c') # Ctrl + c


# 举个例子
# 搜索框先搜索彭于晏,然后Ctrl+x,剪切彭于晏。再重新输入胡歌进行搜索
# 键盘事件
from selenium import webdriver
from selenium.webdriver.common.keys import Keys # 需要导入keys包
import time

driver = webdriver.Edge()
driver.get("https://www.baidu.com/")

driver.find_element_by_id("kw").send_keys("彭于晏")
driver.find_element_by_id("su").submit()
time.sleep(2)

# 键盘的组合键
# 将上诉输入的内容进行剪切,然后重新输入新的内容
# 首先还是需要先定位到元素
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'a')
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'x')
time.sleep(3)

# 重新输入新的数据
driver.find_element_by_id("kw").send_keys("胡歌")
driver.find_element_by_id("kw").send_keys(Keys.ENTER)

time.sleep(3)
driver.quit()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

7、鼠标事件

还是一样的,需要使用到鼠标,首先还是需要先进行导包

from selenium.webdrive.common.action_chains import ActionChains
  • 1

这个类里面有以下几种操作:

  • context_click() 右击

  • double_click() 双击

  • drag_and_drop() 拖动

  • move_to_element() 移动

    from selenium import webdriver
    from selenium.webdriver.common.action_chains import ActionChains
    import time

    driver = webdriver.Edge()
    driver.get(“https://www.baidu.com/”)

    driver.find_element_by_id(“kw”).send_keys(“胡歌”)
    p = driver.find_element_by_id(“su”) # 定位到 百度一下按钮
    ActionChains(driver).double_click§.perform() # 双击百度一下按钮

    time.sleep(6)

    driver.quit()

ActionChains(driver), 生成用户行为。所有的行为都存储在ActionChains对象里面,通过perform()存储的行为。

double_click§,双击p所指向的元素。

perform(),执行所有存储的行为。

8、多层框架和窗口定位

多层框架或窗口的定位:

  • switch_to_frame()
  • switch_to_window()

对于一个现代的web 应用,经常会出现框架(frame) 或窗口(window)的应用,这也就给我们的定位带来了一个难题。有时候我们定位一个元素,定位器没有问题,但一直定位不了,这时候就要检查这个元素是否在一个frame 中,seelnium webdriver 提供了一个switch_to_frame 方法,可以很轻松的来解决这个问题。switch_to_frame(name_or_id_or_frame_element):可以简单记忆一下,如果这个frame有name和id属性那么就用这两个属性就好,如果没有的话可以先用find_element_by_xxx方法找到这个frame元素,然后把这个元素传进去,这也是可行的。switch_to_frame()把当前定位的主体切换了frame里。怎么理解这句话呢?我们可以从frame的实质去理解。
frame中实际上是嵌入了另一个页面,而webdriver每次只能在一个页面识别,因此才需要用switch_to_frame方法去获取frame中嵌入的页面,对那个页面里的元素进行定位。
switch_to_default_content() :从frame中嵌入的页面中跳出,跳回到最外面的原始页面中。

还有可能嵌套的不是框架,而是窗口,还有针对窗口的方法:switch_to_window(),用法与switch_to_frame ()相同:
driver.switch_to_window(“windowName”)

9、上传文件

上传文件也是比较常见的操作,比如在gitee上,重新上传自己账户的头像之类的,都是上传文件的操作。

其实思路还是跟上面介绍的操作一样的,首先还是需要先定位到上传按钮,然后直接send_Keys(),括号里面输入的就是图片的绝对地址

# 首先定位到上传按钮
driver.find_element_by_link_text("上传").send_Keys(图片的路径)
  • 1
  • 2

四、unittest框架

1、批量执行测试用例

在上文,我们在写代码时,都是一个测试用例,就要写一个.py的源文件,而unittest框架,就能够使其简化,这个框架可以将一个测试用例,写成一个函数就行,我们只需要框架,这样就能一次性跑完所有的代码了。unittest 单元测试提供了创建测试用例,测试套件以及批量执行的方案, unittest 在安装pyhton 以后就直接自带了,直接import unittest 就可以使用

作为单元测试的框架, unittest 也是可以对程序最小模块的一种敏捷化的测试。在自动化测试中,我们虽然不需要做白盒测试,但是必须需要知道所使用语言的单元测试框架。利用单元测试框架,创建一个类,该类继承unittest的TestCase,这样可以把每个case看成是一个最小的单元, 由测试容器组织起来,到时候直接执行,同时引入测试报告。

import unittest # 导包

class Test(unittest.TestCase):
    # 写其他函数
  • 1
  • 2
  • 3
  • 4

像这样写,意思就是该类,继承与unittest的TestCase。然后在这个类里面写一个函数就行。那么该如何调用这个类呢?非常简单,如下:

# 调用函数
if __name__ == "__main__":
    unittest.main()
  • 1
  • 2
  • 3

在执行测试用例之前,我们还需要做一些准备工作收尾工作,比如获取浏览器驱动、获取测试网址,又或者是关闭浏览器,这些操作,都是需要写在函数里面的。

  • setUp() : 用于做准备工作的
  • tearDown(): 用于做收尾工作的

完整的代码如下:

import unittest # 导包
from selenium import webdriver

class Test(unittest.TestCase):
    def setUp(self): # 准备工作
        self.driver = webdriver.Edge()# 获取浏览器驱动
        self.url = "https://www.baidu.com/"
        self.driver.maximise() # 浏览器最大化
        
        
    def tearDown(self): # 收尾工作
        self.driver.quit() # 关闭浏览器
        
if __name__ == "__main__":
    unittest.main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

现在大致的样子,就是这样的。接下来就是需要我们写测试用例的代码了。

这个框架有个怪脾气,我们写的测试用例的函数名,必须是以“test_”开头,不然的话,他是不会执行这个函数的。如下

import unittest # 导包
from selenium import webdriver

class Test(unittest.TestCase):
    def setUp(self): # 准备工作
        self.driver = webdriver.Edge()# 获取浏览器驱动
        self.url = "https://www.baidu.com/"
        self.driver.maximise() # 浏览器最大化
        
    def tearDown(self): # 收尾工作
        self.driver.quit() # 关闭浏览器
        
    # 测试:百度搜索 许嵩
    def test_xusong(self):
        driver = self.driver
        driver.get(self.url)
        driver.find_element_by_id("kw").send_keys("许嵩")
        driver.find_element_by_id("su").click()
        time.sleep(3)
              
if __name__ == "__main__":
    unittest.main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

这样,我们就用unittest框架,跑了一个测试用例,如果还有其他测试用例,我们只需要在类里面另外在写一个函数即可。

执行流程

假设有很多测试用例,都写进了测试类里面,在执行代码的时候,每执行一个测试用例,它就是重新调用setUP函数,这个测试用例执行结束之后,也会先调用tearDown函数,然后才执行下一个测试用例

我们还可以使用类似于java中的注解,可以忽略某一个测试用例。

	# 测试:百度搜索 许嵩
    @unittest.skip("kipping") # 表示忽略这个函数,不会执行这个函数
    def test_xusong(self):
        driver = self.driver
        driver.get(self.url)
        driver.find_element_by_id("kw").send_keys("许嵩")
        driver.find_element_by_id("su").click()
        time.sleep(3)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2、unittest断言

除此之外,unittest框架还提供了断言,当测试用例很多时,程序猿眼睛可能是看不完的。这个时候我们就可以使用断言,用于判断实际结果与预期结果不相等时,就会提示测试失败

	# 测试:百度搜索 许嵩
    def test_xusong(self):
        driver = self.driver
        driver.get(self.url)
        driver.find_element_by_id("kw").send_keys("许嵩")
        driver.find_element_by_id("su").click()
        time.sleep(3)
        title = driver.title # 获取当前网页的title
        self.assertEqual(title, "许嵩_百度搜索", msg="与预期结果不一致")
        time.sleep(2)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

如上,当title不相等时,就会提示测试失败,在终端就能够看到这些信息。其他的一些断言方法:

image-20220122140354125

image-20220122140455863

当然,当断言失败,也就是预期结果与实际结果不相等时,我们还可以使用try、except语句,进行处理,将结果进行截图保存。

	@data([u"彭于晏", u"彭于晏_百度搜索"], [u"胡歌", u"胡歌_百度搜索"],[u"理想", u"刘翔_百度搜索"])
    @unpack # 对上诉数据进行打包,用于下面代码测试
    def test_baidu2(self, first_value, second_value):
        driver = self.driver
        driver.get(self.url)
        driver.find_element_by_id("kw").send_keys(first_value)
        driver.find_element_by_id("su").click()
        time.sleep(3)
        title = driver.title
        # self.assertEqual(second_value, title, msg="与描述不符合")
        try:
            self.assertEqual(second_value, title, msg="与描述不符合")
        except:
            self.get_screen(driver, first_value)
            
     def get_screen(self, driver, file_name):
        # 没有这个文件夹,就创建一个
        if not os.path.exists("../htmlResult"):
            os.makedirs("../htmlResult")
        # 获取现在的时间
        nowTime = time.strftime("%Y-%m-%d %H%M%S", time.localtime(time.time()))
        # 获取截图--浏览器的截图
        driver.get_screenshot_as_file('../htmlResult/' + nowTime + file_name + '.png')
        time.sleep(1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

3、HTML测试报告

在所有的测试用例执行完之后,我们还可以自动生成一个测试报告,里面就写清楚了很多信息。我们需要通过HTMLTestRunner.py 来生成测试报告,这个python解释器没有自带,需要自己下载。

HTMLTestRunner下载

然后将下载的包,放到下面这个Lib文件夹里面。

image-20220122141148837

# html报告生成
import os
import unittest
import time
import HTMLTestRunner

# 得到所有测试用例
import demo.demo9

def createSuite():
    # 收集写好的.py的文件
    suite = unittest.defaultTestLoader.loadTestsFromTestCase(demo.demo9.TestBaidu)
    return suite

if __name__ == "__main__":
    if not os.path.exists("../htmlResult"):
        os.makedirs("../htmlResult")
    now_time = time.strftime("%Y-%m-%d %H%M%S", time.localtime(time.time()))
    file_name = "../htmlResult/" + now_time + ".html"
    with open(file_name, 'wb') as fp:
        # 生成HTMLRunner
        runner = HTMLTestRunner.HTMLTestRunner(stream=fp,verbosity=2,title="测试报告",description="用例执行情况")
        suite = createSuite()
        runner.run(suite)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

上诉代码中,使用到了suite。称为单元测试用例的集合,也就是将所有的.py源文件全部集中起来,一起跑代码。有四种得到suite的方式:

image-20220122153933334

4、数据驱动

在上文中的所有代码中,我们在输入参数的时候,都是事先在代码中写好的,不够方便。那么我们可以事先将所有的测试用例写到一个txt文件中,然后我们调用一个函数,从文件中读取所有的测试用例。再使用数据驱动(ddt),将测试用例填入我们的代码中。

python 的unittest 没有自带数据驱动功能。所以如果使用unittest,同时又想使用数据驱动,那么就可以使用DDT来完成 。

# 命令行输入以下代码
pip install ddt # 安装ddt
pip show ddt # 查看ddt
  • 1
  • 2
  • 3

导包:

import sys
import unittest, csv
import os
from selenium import webdriver
import time
from ddt import ddt, unpack, data, file_data # 新加的包
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

要想一个类,能够使用数据驱动,那么需要在这个类的前面写这一行代码:

image-20220122154802271

要想一个函数,能够自动添加测试的数据,就需要在这个函数的前面写这样一行代码:(只需在括号里填数据就行)

image-20220122155107184

或者还可以输入两个参数的形式:

image-20220122155322454

上面这样的代码,虽然能够做到自动添加测试数据,但是还是不够好,如果测试数据有100万行,难道要全部一次性写在函数名前面吗?

显然没必要,此时就用到了txt文件。如下

image-20220122155533119

image-20220122155656834

我的txt文件内容如下,具体改怎么写读取文件的内容,还是要看你的txt文件是怎么洗的。(第一行要写data,表示这是测试数据)

image-20220122160013363

也还可以读取json文件,这里我们就不多介绍了。

好啦,本期更新就到此结束啦,我们下期再见吧!!!

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号