UI自动化测试—数据驱动


在UI自动化测试中,我们经常会碰到相同的测试步骤,不同的测试场景,会把测试的数据分离到文件中来统一管理测试数
据,Json文件也是经常
我们以测试sina邮箱首页登录场景为例,我们需要测试账号密码为空的场景、邮箱格式错误的场景、账号密码不符的场景
正常我们的代码为:
import time
from selenium import webdriver
import unittest

class SinaLogin(unittest.TestCase):
    def setUp(self) -> None:
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.get("https://mail.sina.com.cn/")
        self.driver.implicitly_wait(20)

    def tearDown(self) -> None:
        self.driver.quit()

    def test_sina_null(self):
        '''sina邮箱验证,登录账号秘密为空'''
        self.driver.find_element_by_id('freename').send_keys('')
        self.driver.find_element_by_id('freepassword').send_keys('')
        self.driver.find_element_by_class_name('loginBtn').click()
        divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
        self.assertEqual(divText.text,'请输入邮箱名')

    def test_sina_email_format(self):
        '''sina邮箱验证,登录邮箱格式不正确'''
        self.driver.find_element_by_id('freename').send_keys('qwdqh1231')
        self.driver.find_element_by_id('freepassword').send_keys('12312xs')
        self.driver.find_element_by_class_name('loginBtn').click()
        divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
        self.assertEqual(divText.text,'您输入的邮箱名格式不正确')

    def test_sina_username_error(self):
        '''sina邮箱验证,账号密码不匹配'''
        self.driver.find_element_by_id('freename').send_keys('hc12@sina.cn')
        self.driver.find_element_by_id('freepassword').send_keys('jasbahc12')
        self.driver.find_element_by_class_name('loginBtn').click()
        time.sleep(1)
        divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
        self.assertEqual(divText.text,'登录名或密码错误')

if __name__ == '__main__':
    unittest.main(verbosity=2)
下面以不同的文件分离为例完成自动化的测试

一.Json

首先我们需要把数据分离出来写入Json的文件中,文件路径为:UI自动化测试->data->sina.json
{
  "loginNull": {"username": "","password": "","result": "请输入邮箱名"},
  "emailFormat": {"username": "sadert","password": "asrtr","result": "您输入的邮箱名格式不正确"},
  "loginError": {"username": "sdrtdt@sina.com","password": "aserty","result": "登录名或密码错误"}
}

调用json文件,文件路径为:UI自动化测试->test_sina->utils->operationJson.py

import json
import os

def  base_dir():
    return os.path.dirname(os.path.dirname(os.path.dirname(__file__)))   #当前文件的上上级路径,也就是UI自动化测试

def readJson():
    return json.load(open(os.path.join(base_dir(),'data','sina.json'),encoding='utf-8'))   
'''路径的拼接,找到sina.json文件,然后将文件反序列化读取,并以'utf-8'解码'''

调用json文件的输出结果为一个字典:

{'loginNull': {'username': '', 'password': '', 'result': '请输入邮箱名'}, 'emailFormat': {'username': 'sadert', 'password': 'asrtr', 'result': '您输入的邮箱名格式不正确'}, 'loginError': {'username': 'sdrtdt@sina.com', 'password': 'aserty', 'result': '登录名或密码错误'}}

测试代码:

import time
from selenium import webdriver
import unittest
from UI自动化测试.test_sina.utils.operationJson import readJson

class SinaLogin(unittest.TestCase):
    def setUp(self) -> None:
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.get("https://mail.sina.com.cn/")
        self.driver.implicitly_wait(20)

    def tearDown(self) -> None:
        self.driver.quit()

    def test_sina_null(self):
        '''sina邮箱验证,登录账号秘密为空'''
        self.driver.find_element_by_id('freename').send_keys(readJson()['loginNull']['username'])
        self.driver.find_element_by_id('freepassword').send_keys(readJson()['loginNull']['password'])
        self.driver.find_element_by_class_name('loginBtn').click()
        divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
        self.assertEqual(divText.text,readJson()['loginNull']['result'])

    def test_sina_email_format(self):
        '''sina邮箱验证,登录邮箱格式不正确'''
        self.driver.find_element_by_id('freename').send_keys(readJson()['emailFormat']['username'])
        self.driver.find_element_by_id('freepassword').send_keys(readJson()['emailFormat']['password'])
        self.driver.find_element_by_id('freename').send_keys('jasbahc12')
        self.driver.find_element_by_class_name('loginBtn').click()
        divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
        self.assertEqual(divText.text,readJson()['emailFormat']['result'])

    def test_sina_username_error(self):
        '''sina邮箱验证,账号密码不匹配'''
        self.driver.find_element_by_id('freename').send_keys(readJson()['loginError']['username'])
        self.driver.find_element_by_id('freepassword').send_keys(readJson()['loginError']['password'])
        self.driver.find_element_by_class_name('loginBtn').click()
        time.sleep(1)
        divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
        self.assertEqual(divText.text,readJson()['loginError']['result'])

if __name__ == '__main__':
    unittest.main()

二.Yaml

yaml文件详解:https://ruanyifeng.com/blog/2016/07/yaml.html

Yaml语言的基本语法规则如下: 大小写敏感 使用缩进表示层级关系 缩进时不允许使用Tab键,只允许使用空格。 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
在Python中操作Yaml文件我们需要独立安装第三方的pyyaml库,安装命令为:
pip3 install pyyaml
首先我们需要把数据分离出来写到yaml文件中,路径为:UI自动化测试->data->sina.yaml
loginNull:
  username: ""
  password: ""
  result: "请输入邮箱名"
emailFormat:
  username: "21gasyfq1"
  password: "12sq2"
  result: "您输入的邮箱名格式不正确"
loginError:
  username: "121ssx@sina.com"
  password: "1232szaxs"
  result: "登录名或密码错误"

调用json文件,文件路径为:UI自动化测试->test_sina->utils->operationYaml.py

import os
import yaml

def base_dir():
    return os.path.dirname(os.path.dirname(os.path.dirname(__file__)))  #查找文件路径

'''路径的拼接和文件读取'''
def readYaml(): with open( os.path.join(base_dir(),'data','sina.yaml'), encoding='utf-8') as f: return yaml.safe_load(f)
我们查看调用yaml文件函数的输出结果为字典:
{'loginNull': {'username': '', 'password': '', 'result': '请输入邮箱名'}, 'emailFormat': {'username': '21gasyfq1', 'password': '12sq2', 'result': '您输入的邮箱名格式不正确'}, 'loginError': {'username': '121ssx@sina.com', 'password': '1232szaxs', 'result': '登录名或密码错误'}}

测试代码:

import time
from selenium import webdriver
import unittest
from UI自动化测试.test_sina.utils.operationYaml import readYaml

class SinaLogin(unittest.TestCase):
    def setUp(self) -> None:
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.get("https://mail.sina.com.cn/")
        self.driver.implicitly_wait(20)

    def tearDown(self) -> None:
        self.driver.quit()

    def test_sina_null(self):
        '''sina邮箱验证,登录账号秘密为空'''
        self.driver.find_element_by_id('freename').send_keys(readYaml()['loginNull']['username'])
        self.driver.find_element_by_id('freepassword').send_keys(readYaml()['loginNull']['password'])
        self.driver.find_element_by_class_name('loginBtn').click()
        divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
        self.assertEqual(divText.text,readYaml()['loginNull']['result'])

    def test_sina_email_format(self):
        '''sina邮箱验证,登录邮箱格式不正确'''
        self.driver.find_element_by_id('freename').send_keys(readYaml()['emailFormat']['username'])
        self.driver.find_element_by_id('freepassword').send_keys(readYaml()['emailFormat']['password'])
        self.driver.find_element_by_id('freename').send_keys('jasbahc12')
        self.driver.find_element_by_class_name('loginBtn').click()
        divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
        self.assertEqual(divText.text,readYaml()['emailFormat']['result'])

    def test_sina_username_error(self):
        '''sina邮箱验证,账号密码不匹配'''
        self.driver.find_element_by_id('freename').send_keys(readYaml()['loginError']['username'])
        self.driver.find_element_by_id('freepassword').send_keys(readYaml()['loginError']['password'])
        self.driver.find_element_by_class_name('loginBtn').click()
        time.sleep(1)
        divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
        self.assertEqual(divText.text,readYaml()['loginError']['result'])

if __name__ == '__main__':
    unittest.main()

三.Csv

首先我们拿到的excel文件格式转化为csv文件:Excel->文件->另存为->csv文件,切记不可直接更改文件后缀格式

把文件移到到路径为:UI自动化测试->data->sina.csv
username,password,result
,,请输入邮箱名
12sdedwqfg,Asrety,您输入的邮箱名格式不正确
awesras@sina.com,sdfdrtsdzf,登录名或密码错误

调用csv文件:文件路径为:UI自动化测试->test_sina->utils->operationCsv.py


以字典的形式读取csv文件:
import os
import csv

def base_dir():
    return os.path.dirname(os.path.dirname(os.path.dirname(__file__)))

def readCsvDict():
    lists=[]
    with open(os.path.join(base_dir(),'data','sina.csv'),encoding='utf-8-sig') as f:
        reader=csv.DictReader(f)
        for item in reader:
            lists.append(dict(item))
    return lists

 输出的内容为列表加字典:

[{'username': '', 'password': '', 'result': '请输入邮箱名'}, {'username': '12sdedwqfg', 'password': 'Asrety', 'result': '您输入的邮箱名格式不正确'}, {'username': 'awesras@sina.com', 'password': 'sdfdrtsdzf', 'result': '登录名或密码错误'}]

测试代码:

import time
from selenium import webdriver
import unittest
from UI自动化测试.test_sina.utils.operationCsv import readCsvDict

class SinaLogin(unittest.TestCase):
    def setUp(self) -> None:
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.get("https://mail.sina.com.cn/")
        self.driver.implicitly_wait(20)

    def tearDown(self) -> None:
        self.driver.quit()

    def test_sina_null(self):
        '''sina邮箱验证,登录账号秘密为空'''
        self.driver.find_element_by_id('freename').send_keys(readCsvDict()[0]['username'])
        self.driver.find_element_by_id('freepassword').send_keys(readCsvDict()[0]['password'])
        self.driver.find_element_by_class_name('loginBtn').click()
        divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
        self.assertEqual(divText.text,readCsvDict()[0]['result'])

    def test_sina_email_format(self):
        '''sina邮箱验证,登录邮箱格式不正确'''
        self.driver.find_element_by_id('freename').send_keys(readCsvDict()[1]['username'])
        self.driver.find_element_by_id('freepassword').send_keys(readCsvDict()[1]['password'])
        self.driver.find_element_by_id('freename').send_keys('jasbahc12')
        self.driver.find_element_by_class_name('loginBtn').click()
        divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
        self.assertEqual(divText.text,readCsvDict()[1]['result'])

    def test_sina_username_error(self):
        '''sina邮箱验证,账号密码不匹配'''
        self.driver.find_element_by_id('freename').send_keys(readCsvDict()[2]['username'])
        self.driver.find_element_by_id('freepassword').send_keys(readCsvDict()[2]['password'])
        self.driver.find_element_by_class_name('loginBtn').click()
        time.sleep(1)
        divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
        self.assertEqual(divText.text,readCsvDict()[2]['result'])

if __name__ == '__main__':
    unittest.main()

 



以列表的形式读取csv文件:

import os
import csv

def base_dir():
    return os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
def readCsvList():
    '''以列表的形式读取文件'''
    lists=[]
    with open(os.path.join(base_dir(), 'data', 'sina.csv'), encoding='utf-8-sig') as f:
        reader=csv.reader(f)
        next(reader)
        for item in reader:
            lists.append(item)
    return lists

输出的内容为列表:

[['', '', '请输入邮箱名'], ['12sdedwqfg', 'Asrety', '您输入的邮箱名格式不正确'], ['awesras@sina.com', 'sdfdrtsdzf', '登录名或密码错误']]

测试代码:

import time
from selenium import webdriver
import unittest
from UI自动化测试.test_sina.utils.operationCsv import readCsvList

class SinaLogin(unittest.TestCase):
    def setUp(self) -> None:
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.get("https://mail.sina.com.cn/")
        self.driver.implicitly_wait(20)

    def tearDown(self) -> None:
        self.driver.quit()

    def test_sina_null(self):
        '''sina邮箱验证,登录账号秘密为空'''
        self.driver.find_element_by_id('freename').send_keys(readCsvList()[0][0])
        self.driver.find_element_by_id('freepassword').send_keys(readCsvList()[0][1])
        self.driver.find_element_by_class_name('loginBtn').click()
        divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
        self.assertEqual(divText.text,readCsvList()[0][2])

    def test_sina_email_format(self):
        '''sina邮箱验证,登录邮箱格式不正确'''
        self.driver.find_element_by_id('freename').send_keys(readCsvList()[1][0])
        self.driver.find_element_by_id('freepassword').send_keys(readCsvList()[1][1])
        self.driver.find_element_by_class_name('loginBtn').click()
        divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
        self.assertEqual(divText.text,readCsvList()[1][2])

    def test_sina_0_error(self):
        '''sina邮箱验证,账号密码不匹配'''
        self.driver.find_element_by_id('freename').send_keys(readCsvList()[2][0])
        self.driver.find_element_by_id('freepassword').send_keys(readCsvList()[2][1])
        self.driver.find_element_by_class_name('loginBtn').click()
        time.sleep(1)
        divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
        self.assertEqual(divText.text,readCsvList()[2][2])

if __name__ == '__main__':
    unittest.main()

四.Excel

在Python中操作Excel文件我们需要独立安装第三方的xlrd库,安装命令为:
pip3 install xlrd
首先我们拿到的excel文件移到路径为:UI自动化测试->data->sina.xls
调用Excel文件:文件路径为:UI自动化测试->test_sina->utils->operationExcel.py
import xlrd
import os

def base_dir():
    return os.path.dirname(os.path.dirname(os.path.dirname(__file__)))

def readExcal():
    lists=[]    #定义一个列表
    sheet=xlrd.open_workbook(os.path.join(base_dir(),'data','sina.xls'))
    book=sheet.sheet_by_index(0)   #通过索引定位到Excel表格的第一张
    for item in range(1,book.nrows):  #因为第一行是属性,所以不使用,从索引1开始循环第一张的所有单元格
        lists.append(book.row_values(item))  #返回切片单元格的值添加到列表lists中
    return lists

输出的结果为一个列表:

[['', '', '请输入邮箱名'], ['sdfsdfsg', 'Asrety', '您输入的邮箱名格式不正确'], ['awesras@sina.com', 'sdfdrtsdzf', '登录名或密码错误']]

测试代码:

from selenium import webdriver
import unittest
import time as t
from UI自动化测试.test_sina.utils.operationExcel import readExcel

class sinaTest(unittest.TestCase):
    def setUp(self) -> None: 
        self.driver=webdriver.Chrome()
        self.driver.get('https://mail.sina.com.cn/')
        self.driver.maximize_window()
        self.driver.implicitly_wait(30)

    def tearDown(self) -> None: 
        self.driver.quit()

    def test_sina_null(self):
        '''sina邮箱验证:登录账户为空'''
        self.driver.find_element_by_id('freename').send_keys(readExcel()[0][0])
        self.driver.find_element_by_id('freepassword').send_keys(readExcel()[0][1])
        self.driver.find_element_by_class_name('loginBtn').click()
        t.sleep(3)
        divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
        self.assertEqual(divText.text,readExcel()[0][2])

    def test_sina_email_format(self):
        '''sina邮箱验证:登录邮箱格式不正确'''
        self.driver.find_element_by_id('freename').send_keys(readExcel()[1][0])
        self.driver.find_element_by_id('freepassword').send_keys(readExcel()[1][1])
        self.driver.find_element_by_class_name('loginBtn').click()
        t.sleep(3)
        divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
        self.assertEqual(divText.text,readExcel()[1][2])

    def test_sina_username_error(self):
        '''sina邮箱验证:登录账户密码不匹配'''
        self.driver.find_element_by_id('freename').send_keys(readExcel()[2][0])
        self.driver.find_element_by_id('freepassword').send_keys(readExcel()[2][1])
        self.driver.find_element_by_class_name('loginBtn').click()
        t.sleep(3)
        divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
        self.assertEqual(divText.text,readExcel()[2][2])

if __name__ == '__main__':
    unittest.main()

五.MysQl