自动化测试框架搭建-配置-1

先从一个脚本test_baidu.py开始,目的是模拟在Chrome浏览器的百度界面上搜索一个关键字“自动化测试unittest”.在线安装selenium这里自不必说,通过 pip install selenuim 进行在线安装

#coding:utf-8

import os
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

URL = "http://www.baidu.com"
base_path = os.path.abspath(os.path.abspath(__file__)+'\...')
driver_path = os.path.abspath(base_path + '\drivers\chromedriver.exe')

locator_kw = (By.ID,'kw')
locator_su = (By.ID,'su')
locator_result = (By.XPATH,'//div[contains(@class, "result")]/h3/a')

driver = webdriver.Chrome(executable_path=driver_path)
driver.get(URL)

driver.find_element(*locator_kw).send_keys("自动化测试unitest")
driver.find_element(*locator_su).click()
time.sleep(2)
links = driver.find_element(*locator_result)
for link in links:
    print (link.text)
driver.quit()

提示:Message:'Chromedriver.exe' executable needs to be in PATH.

将该驱动加入到环境变量PATH中


发现该问题没有解决,将chromedriver.exe拷贝至当前工作目录,这里的工作目录是


此时不在弹出path路径没有引用的问题,在打开浏览器时提示:请停用以开发者模式运行的扩展程序:


    出现这样的对话框,如果不能自动关闭,这个对话框会影响web端页面的其他链接的定位识别,这样就会导致该脚本就没法正常完成。 想过多种方法,如何关闭开发者模式等方法,在本地的时候,已经手动关闭了开发者模式,但是在运行脚本的过程中,该对话框一直存在。最后无解,在处理脚本过程中,为了规避这个对话框,我采取的方法是,在输入URL后,就将打开的页面设置最大化,即在适当的位置输入 driver.maximize_window() ,但是这样的方法只是暂时规避了,在运行脚本的过程中,该对话框是一直存在的。 最后发现是版本不一致的原因。简单来说,更新Chromedriver.exe与Chrome浏览器版本保持一致。

chromedriver下载


如果版本chrome版本较新,可能找不到对应的关系,但是稍微推理下就不难发现,从chromedriver的V2.*版本和支持的Chrome版本的逻辑对应关系,就不难找到自己chrome版本的chromedriver版本,如自己的chrome版本为:


自然对应的chromedriver版本为V2.37版本,支持的chrome版本为66-68,下载之后放在当前工作目录(和test_baidu.py同一目录)下,就可以解决上述问题。

URL = "http://www.baidu.com"
#base_path = os.path.abspath(os.path.abspath(__file__)+'\...')
#driver_path = os.path.abspath(base_path + '\drivers\chromedriver.exe')
driver_path = os.path.abspath('chromedriver.exe')

locator_kw = (By.ID,'kw')
locator_su = (By.ID,'su')
locator_result = (By.XPATH,'//div[contains(@class, "result")]/h3/a')

driver = webdriver.Chrome(executable_path=driver_path)
driver.maximize_window()
driver.get(URL)

搜索框中定位了kw元素,“百度一下”按钮定位了 su 元素,如下图所示:


运行脚本发现百度搜索界面可以正常弹出,但是没有在搜索框中搜索“自动化测试unittest”,尽管开始加了coding:utf-8,但是还有有怀疑是否不支持中文,去掉中文“自动化测试”进行试验

driver.find_element(*locator_kw).send_keys("unittest")

可以正常搜索,但是为什么不能键入中文呢?还请指教


       但是为了搭建一个将数据和测试用例分离的轻量级测试框架,需要做的是将驱动放置在drivers下,而不是放置在当前目录(将chromedriver.exe和test_baidu.py放置在同一目录)下,将chromedriver.exe放置到新建的driver目录下,将上述获取chromedriver.exe的路径进行修改 。  

#coding:utf-8

import os
import time
from selenium import webdriver
from selenium.webdriver.common.by import By


URL = "http://www.baidu.com"
#base_path = os.path.abspath(os.path.abspath(__file__)+'\...')
#driver_path = os.path.abspath(base_path + '\drivers\chromedriver.exe')
#driver_path = os.path.abspath('chromedriver.exe')

DirPath = os.path.dirname(os.path.dirname(__file__))
#print DirPath
driver_path = os.path.join(DirPath, '../drivers/chromedriver.exe')#这里也可以去掉"../"
#print driver_path

locator_kw = (By.ID,'kw')
locator_su = (By.ID,'su')
locator_result = (By.XPATH,'//div[contains(@class, "result")]/h3/a')


driver = webdriver.Chrome(executable_path=driver_path)
driver.maximize_window()
driver.get(URL)

driver.find_element(*locator_kw).send_keys("unittest")
driver.find_element(*locator_su).click()
#driver.find_element(*locator_wd).click()
time.sleep(2)
links = driver.find_element(*locator_result)
for link in links:
    print (link.text)
driver.quit()

     模块中在路径访问上,最初使用了绝对路径进行访问,但是绝对路径访问时存在问题,因为通过abspath()获取的是..xx\xx\xx..行的window下的路径,从而使得python在使用的时候很不方便,容易出现The file is not exist的错误,因此这里改用dirname()方法结合使用os.path.join()方法获得路径,对于其中的用法参考python路径问题。这样就实现了各个模块的分离。对于其中使用XPath进行元素定位的方法,可以参考XPath详解对于只搜索一次,使用函数的方法也可以,但是selenium的强大之处就在于自动操作浏览器来做很多事情,它可以模拟我们与浏览器的交互,因此如果想要搜索“Python”,是不是要再创建一个脚本?还是把原来的脚本修改一下?或者我们可以用 unittest 来改一下,实现类的方法,把两次搜索分别写一个测试方法test_baidu1.py:

#coding:utf-8
#test_baidu1.py
import os
import time
import unittest
from selenium import webdriver
from selenium.webdriver.common.by import By


class TestBaiDu(unittest.TestCase):
    URL = "http://www.baidu.com"
    #driver_path = os.path.abspath('chromedriver.exe')
    DirPath = os.path.dirname(os.path.dirname(__file__))
    driver_path = os.path.join(DirPath, '../drivers/chromedriver.exe') #这里也可以去掉"../"

    locator_kw = (By.ID, 'kw')
    locator_su = (By.ID, 'su')
    locator_result = (By.XPATH, '//div[contains(@class, "result")]/h3/a')

    def setUp(self):
        self.driver = webdriver.Chrome(executable_path=self.driver_path)
        self.driver.get(self.URL)
        self.driver.maximize_window()

    def tearDown(self):
        self.driver.quit()

    def test_search_0(self):
        self.driver.find_element(*self.locator_kw).send_keys('unittest')
        self.driver.find_element(*self.locator_su).click()
        time.sleep(2)
        links = self.driver.find_elements(*self.locator_result)
        for link in links:
            print(link.text)

    def test_search_1(self):
        self.driver.find_element(*self.locator_kw).send_keys('Python')
        self.driver.find_element(*self.locator_su).click()
        time.sleep(2)
        links = self.driver.find_elements(*self.locator_result)
        for link in links:
            print(link.text)


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

显示的过程为:首先打开chrome浏览器的百度搜索框,并开始搜索“unittest”;接着关闭该界面,再次打开chrome的百度搜索页面,搜索“python”关键字,最后关闭。


打印的输出结果:


      现在让搜索的目标数据和搜索的实现类进行分离,这样避免了多次在源代码上操作,如果需要修改搜索的地址,只需要在“配置”文件中进行修改。将配置抽出来放到config.yml中:

在工程framework下新建一个package,命名为config,并在config下新建一个config.yaml文件,由于无法直接通过右键/新建的形式直接建立yaml文件,可以在本地package下新建一个txt文件,再修改文件后缀为.yaml,编辑的时候使用notepad打开即可


URL: http://www.baidu.com

按照搭建测试框架目录中的结构,为了读取yaml文件,我们需要一个封装YamlReader类,在utils(公共方法)中创建file_reader.py文件,同样新建一个utils的package,并创建file_reader.py脚本:

#coding:utf-8
import yaml
import os


class YamlReader():
    def __init__(self, yamlf):
        if os.path.exists(yamlf):
            self.yamlf = yamlf
        else:
            raise FileNotFoundError('文件不存在!')
        self._data = None

    @property
    def data(self):
        # 如果是第一次调用data,读取yaml文档,否则直接返回之前保存的数据
        if not self._data:
            with open(self.yamlf, 'rb') as f:
                self._data = list(yaml.safe_load_all(f))  # load后是个generator,用list组织成列表
        return self._data

对于如何使用@property可以参考学习@property,而且我们需要一个Config类来读取配置,将该模块放置在config这package种,因此config.py:

#coding:utf-8
"""
读取配置。这里配置文件用的yaml,也可用其他如XML,INI等,需在file_reader中添加相应的Reader进行处理。
"""
import os
from utils.file_reader import YamlReader

# 通过当前文件的绝对路径,其父级目录一定是框架的base目录,然后确定各层的绝对路径。如果你的结构不同,可自行修改。
# 之前直接拼接的路径,修改了一下,用现在下面这种方法,可以支持linux和windows等不同的平台,也建议大家多用os.path.split()
# 和os.path.join(),不要直接+'\\xxx\\ss'这样
BASE_PATH = os.path.split(os.path.dirname(os.path.abspath(__file__)))[0]
CONFIG_FILE = os.path.join(BASE_PATH, 'config', 'config.yml')
DATA_PATH = os.path.join(BASE_PATH, 'data')
DRIVER_PATH = os.path.join(BASE_PATH, 'drivers')
LOG_PATH = os.path.join(BASE_PATH, 'log')
REPORT_PATH = os.path.join(BASE_PATH, 'report')


class Config:
    def __init__(self, config=CONFIG_FILE):
        self.config = YamlReader(config).data

    def get(self, element, index=0):
        """
        yaml是可以通过'---'分节的。用YamlReader读取返回的是一个list,第一项是默认的节,如果有多个节,可以传入index来获取。
        这样我们其实可以把框架相关的配置放在默认节,其他的关于项目的配置放在其他节中。可以在框架中实现多个项目的测试。
        """
        return self.config[index].get(element)

但是运行的时候,提示没有模块No Module named file_reader


修改加载file_reader模块的路径,这里工程名字叫Franmework为,从根一级路径开始加载路径:

from Framework.utils.file_reader import YamlReader

对于此处可能出现:The file is not exits!


需要将绝对路径更改为相对路径,关于使用路径的问题可以参考python中路径获取以CONFIG_FILE为例:

BASE_PATH = os.path.dirname(os.path.dirname(__file__))
CONFIG_FILE = os.path.join(BASE_PATH, 'config/config.yaml')

再次修改test_baidu2.py脚本:

#coding:utf-8
import time
import unittest
from selenium import webdriver
from selenium.webdriver.common.by import By
from utils.config import Config, DRIVER_PATH


class TestBaiDu(unittest.TestCase):
    URL = Config().get('URL')

    locator_kw = (By.ID, 'kw')
    locator_su = (By.ID, 'su')
    locator_result = (By.XPATH, '//div[contains(@class, "result")]/h3/a')

    def setUp(self):
        self.driver = webdriver.Chrome(executable_path=DRIVER_PATH + '\chromedriver.exe')
        self.driver.get(self.URL)

    def tearDown(self):
        self.driver.quit()

    def test_search_0(self):
        self.driver.find_element(*self.locator_kw).send_keys('selenium')
        self.driver.find_element(*self.locator_su).click()
        time.sleep(2)
        links = self.driver.find_elements(*self.locator_result)
        for link in links:
            print(link.text)

    def test_search_1(self):
        self.driver.find_element(*self.locator_kw).send_keys('Python selenium')
        self.driver.find_element(*self.locator_su).click()
        time.sleep(2)
        links = self.driver.find_elements(*self.locator_result)
        for link in links:
            print(link.text)


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

因此测试框架为:



猜你喜欢

转载自blog.csdn.net/rhx_qiuzhi/article/details/80357757