python 和 selenium实现web UI功能自动化测试框架

以前分享了python和requests搭配实现的接口自动化测试框架,今天,我再来整理分析下基于python和selenium的web UI自动化测试,但愿能对你们有所帮助,也是本身整理知识学习的方法,跟你们一块儿努力,奋斗在自动化测试的道路上。html

其实UI自动化和接口自动化框架的设计思路大同小异,主要目的仍是分离业务代码和测试数据,达到代码的复用,提升测试用例的可维护性以及最最重要的减小人工劳动力。那么就开始直接看正文吧。python

设计目的:web

分离业务代码和测试数据,提升代码可维护性,实现自动化,减小重复劳动,最终达到“偷懒”的目的,哈哈哈哈哈~~ 哎呦,很差意思,一不当心暴露了真相。小编是真的在一本正经的写代码啦。chrome

框架目录结构:api

        case:存放具体的测试代码浏览器

        comm:存放共通的方法app

        file:存放测试用例等测试过程当中用到的测试数据框架

        result:每次测试的log和测试报告的存放位置学习

        caseList:规定执行哪些测试测试

        config:配置静态数据

                                                                readConfig:读取config文件内容

                                                                runAll:测试执行入口文件

一块儿来看整个框架的搭建。

首先,要保证你的python已经安装了selenium包,若是你是用pip来管理本身的python环境的,那么你能够经过下面的命令来导入selenium模块:

pip install selenium

而后,你须要到网上去下载对应浏览器的驱动,这里小编使用的是chrome浏览器,(chrome下载地址:http://chromedriver.storage.googleapis.com/index.html)。下载完成以后呢,将下载的浏览器驱动放到本地的python安装目录下,这样就能够直接在框架中使用了。至此,必备的条件都有了,咱们就能够开工啦。

这里呢,咱们就只挑部份内容进行讲解,有许多跟接口测试框架相同或类似的方法和文件,就不一一进行二次说明了,第一次看的盆友们,有不明白的地方能够看这篇文章,进行补充学习http://www.javashuo.com/article/p-koqjlcfy-ku.html

打开浏览器:

from selenium import webdriver

class Driver:

    def __init__(self):
        
        self.browser = webdriver.Chrome()

    def open_browser(self):
        """
        Do something for browser
        :return: browser
        """
        # 窗口最大化
        self.browser.maximize_window()

        # 打开地址连接
        url = 'http://www.baidu.com'
        self.browser.get(url)
        return self.browser

    def close_browser(self):
        """
        quit browser
        :return:
        """
        self.browser.quit()

从上面的代码能够看出,咱们进行了打开/关闭浏览器的方法定义,只有简单的几行代码,固然了,这里为了方便你们观看,我把url地址直接写了出来,在实际操做时,咱们能够将其抽离出来,根据本身的须要,传入不一样的url地址。这就留着让你们去本身实现吧。

一个简单的搜索栗子:

from time import sleep
from selenium import webdriver
import unittest


class Login(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.Chrome()

        # 窗口最大化
        self.driver.maximize_window()
        self.msg = '海贼王'
        self.url = 'http://www.baidu.com'

    def testSearch(self):
        """
        test body
        :return:
        """
        # open browser
        self.driver.get(self.url)
        sleep(3)
        # click search input
        self.driver.find_element_by_id('kw').click()
        sleep(1)

        # input value
        self.driver.find_element_by_id('kw').send_keys(self.msg)
        sleep(1)
        self.driver.find_element_by_id('su').click()
        sleep(1)

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

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

在上面的代码里,咱们在百度里搜索了小编最爱的动漫,嘻嘻,是否是很开心啊,就这样边学边玩耍,感受测试也是美美的。

selenium能够经过不少种方式来定位元素。这个读者能够自行学习。

你们看到了,这就是UI测试的雏形,有了这个雏形,咱们就能够对它进行扩展,扩展,最后搭出框架来。

添加log日志:

在上面的基础上,咱们能够添加执行时输出的log日志。因此开始写log文件,并将它放在comm文件夹下,做为共同方法来用。这部份内容在接口测试框架那里已经介绍过了,因此请还不清楚的朋友们移步此处:http://www.javashuo.com/article/p-koqjlcfy-ku.html

抽离出浏览器的相关操做:

咱们能够将对浏览器的操做剥离出来,单独放到一个文件中,这样既清晰,又避免了重复的代码操做。并且维护起来也比较方便。

from selenium import webdriver
from comm.Log import MyLog as Log
import readConfig
import threading

localReadConfig = readConfig.ReadConfig()


class Driver:

    def __init__(self):
        self.log = Log.get_log()
        self.logger = self.log.get_logger()

        self.browser = webdriver.Chrome()

    def open_browser(self, name1, name2):
        """
        Do something for browser
        :return: browser
        """
        self.logger.info("Open browser")

        # 窗口最大化
        self.browser.maximize_window()

        # 打开地址连接
        url = localReadConfig.get_webServer(name1, name2)
        self.browser.get(url)
        return self.browser

    def close_browser(self):
        """
        quit browser
        :return:
        """
        self.browser.quit()
        self.logger.info("Quit browser")

    def get_driver(self):
        """
        get web driver
        :return:
        """
        return self.browser


class MyDriver:

    driver = None
    mutex = threading.Lock()

    def __init__(self):
        pass

    @staticmethod
    def get_browser():

        if MyDriver.driver is None:
            MyDriver.mutex.acquire()
            MyDriver.driver = Driver()
            MyDriver.mutex.release()

        return MyDriver.driver

if __name__ == "__main__":
    driver = MyDriver.browser()
    browser = driver.open_browser()

以上即是小编剥离出来的部分,而且将它放到了单独的线程中。

有木有以为眼熟呢?其实就跟log的原理是同样的啦。这就是“触类旁通”哦,套路就是那个套路,就看你怎么用了。

关于Element的那些事儿:

作过UI功能测试的朋友们应该都知道,元素是咱们测试最基本也是最重要的东西,觉得它是咱们直接的操做对象,因此,处理好它们,咱们就会省掉不少的麻烦,因此呢,接下来,小编将会继续分享本身处理element的一些方法,但愿能对你们有所帮助,若是哪位大神有更好的方法,请必定要告诉小编哦!小编在此先谢过了!

class Element:

    def __init__(self, activity_name, element_name):

        self.driver1 = Driver.get_browser()
        self.driver = self.driver1.get_driver()
        self.activity = activity_name
        self.element = element_name
        element_dict = get_el_dict(self.activity, self.element)
        self.pathType = element_dict.get('pathType')
        self.pathValue = element_dict.get('pathValue')

    def is_exist(self):
        """
        Determine element is exist
        :return: TRUE OR FALSE
        """
        try:
            if self.pathType == 'ID':
                self.driver.find_element_by_id(self.pathValue)
                return True
            if self.pathType == 'XPATH':
                self.driver.find_elements_by_xpath(self.pathValue)
                return True
            if self.pathType == 'CLASSNAME':
                self.driver.find_element_by_class_name(self.pathValue)
                return True
            if self.pathType == 'NAME':
                self.driver.find_element_by_name(self.pathValue)
                return True
        except NoSuchElementException:
            return False

    def wait_element(self, wait_time):
        """
        wait element appear in time
        :param wait_time: wait time
        :return: true or false
        """
        time.sleep(wait_time)
        if self.is_exist():
            return True
        else:
            return False

    def get_element(self):
        """
        get element
        :return: element
        """
        try:
            if self.pathType == 'ID':
                element = self.driver.find_element_by_id(self.pathValue)
                return element
            if self.pathType == 'XPATH':
                element = self.driver.find_elements_by_xpath(self.pathValue)
                return element
            if self.pathType == 'CLASSNAME':
                element = self.driver.find_element_by_class_name(self.pathValue)
                return element
            if self.pathType == 'NAME':
                element = self.driver.find_element_by_name(self.pathValue)
                return element
        except NoSuchElementException:
            return None

    def get_element_by_index(self, index):
        """
        get element by index
        :param index: index
        :return: element
        """
        try:
            if self.pathType == 'ID':
                element = self.driver.find_element_by_id(self.pathValue)
                return element[index]
            if self.pathType == 'XPATH':
                element = self.driver.find_elements_by_xpath(self.pathValue)
                return element[index]
            if self.pathType == 'CLASSNAME':
                element = self.driver.find_element_by_class_name(self.pathValue)
                return element[index]
            if self.pathType == 'NAME':
                element = self.driver.find_element_by_name(self.pathValue)
                return element[index]
        except NoSuchElementException:
            return None

    def get_element_list(self):
        """
        get element list
        :return: element list
        """
        try:
            if self.pathType == 'ID':
                element_list = self.driver.find_element_by_id(self.pathValue)
                return element_list
            if self.pathType == 'XPATH':
                element_list = self.driver.find_elements_by_xpath(self.pathValue)
                return element_list
            if self.pathType == 'CLASSNAME':
                element_list = self.driver.find_element_by_class_name(self.pathValue)
                return element_list
            if self.pathType == 'NAME':
                element_list = self.driver.find_element_by_name(self.pathValue)
                return element_list
        except NoSuchElementException:
            return None

    def click(self):
        """
        click element
        :return:
        """
        element = self.get_element()
        time.sleep(1)
        element.click()

    def send_key(self, key):
        """
        input key
        :param key: input value
        :return:
        """
        element = self.get_element()
        time.sleep(1)
        element.clear()
        element.send_keys(key)

    def input_keys(self, index, key):
        """
        By index send key
        :param index: index
        :param key: key
        :return:
        """
        element = self.get_element_by_index(index)
        time.sleep(1)
        element.clear()
        element.send_keys(key)

    def get_text_value(self):
        """
        get attribute
        :return:
        """
        element = self.get_element()
        value = element.get_attribute('text')
        return str(value)

这是小编写的,目前能用到的关于element的方法了,累觉不爱啊~

可是,生活还要继续,工做还未完成。因此,请让我讲完剩下的代码吧!!!

那些让人费神的测试数据文件:

每个好的测试,都离不开一份好的测试用例数据,那么,这么多的数据,咱们要怎样进行管理才能既不乱又方便之后对数据进行更改维护呢?下面,小编就要告诉朋友们一个重磅消息,敲黑板!!!

其实,小编也不知道有什么好办法,小编就是使用excel文件来对测试用例进行统一管理的。请看下面:

形式就是这么个形式,内容就随便大家怎么修改了。毕竟我也只能帮大家到这里了。至于对excel文件内容的读取,在接口测试那篇博文中也有详细介绍哦。不明白的同窗请移步:http://www.javashuo.com/article/p-koqjlcfy-ku.html

其实,出来测试用例,还有一个数量庞大的数据群体,快猜猜它们是谁???

当当当,答案就是:元素定位的数据,包括:id,name,classname,xpath等等,这些数据但是咱们在测试过程当中找到页面元素的不二法门哦。。。因此各位朋友必定要注意啦,必定要处理好它们。

请看下面:

愚蠢的小编就用xml文件来管理啦。

是否是又有人想问怎么读取xml文件了?嘿嘿。。。我不会告诉你的,由于我在前面的博文里已经讲过啦!讲过啦!过啦!啦!!

至此呢,今天的内容也结束了,但愿对你们有所启发和帮助,虽然讲的有些凌乱,不过只要弄懂了这些划分和实现方法,我相信,你也必定能够写出本身满意的UI自动化测试框架。因此,咱们一块儿加油吧。

PS:有些没有提到的部分,因为跟以前介绍接口自动化框架的内容同样,因此就再也不累述,有想了解的朋友,移步此处便可。谢谢!http://www.javashuo.com/article/p-koqjlcfy-ku.html

 

本文为原创文章,转载请注明原文地址,谢谢你们的支持。但愿你们一块儿努力成长。

相关文章
相关标签/搜索