Python and selenium implement automated testing framework for web UI functions (MiTu 888)

https://my.oschina.net/u/3041656/blog/857676

https://pan.baidu.com/s/1jIqpu8A


I shared the interface automation testing framework implemented by python and requests before. Today, I will analyze and analyze the web UI automation testing based on python and selenium. I hope it can be helpful to you. It is also a way to organize knowledge and learn by yourself. Work hard and strive on the road of automated testing.

In fact, the design ideas of UI automation and interface automation frameworks are similar. The main purpose is to separate business code and test data, achieve code reuse, improve the maintainability of test cases, and most importantly, reduce manual labor. Then start reading directly to the text.

aim of design:

Separate business code and test data, improve code maintainability, realize automation, reduce duplication of labor, and finally achieve the goal of "lazy", hahahaha~~ Oh, sorry, I accidentally exposed the truth. The editor is really serious about writing code.

Framework directory structure:

        case: store specific test code

        comm: store the common method

        file: store the test data used in the test process such as test cases

        result: the storage location of the log and test report of each test

        caseList: specifies which tests to execute

        config: configure static data

                                                                readConfig: read the contents of the config file

                                                                runAll: test execution entry file

Let's take a look at the construction of the entire framework.

First, make sure that your python has the selenium package installed. If you use pip to manage your python environment, then you can import the selenium module with the following command:

pip install selenium

Then, you need to go to the Internet to download the driver of the corresponding browser. Here I use the chrome browser, (chrome download address: http://chromedriver.storage.googleapis.com/index.html ). After the download is complete, put the downloaded browser driver in the local python installation directory, so that it can be used directly in the framework. At this point, the necessary conditions are in place, and we can start working.

Here, we will only pick a part of the content to explain. There are many methods and files that are the same or similar to the interface testing framework, so we will not explain them one by one. For those of you who read it for the first time, there are some things you don't understand. You can read this article for supplementary learning https://my.oschina.net/u/3041656/blog/820023

Open the browser:

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()

As can be seen from the above code, we have defined the method of opening/closing the browser. There are only a few simple lines of code. Of course, for the convenience of everyone here, I wrote the url address directly. In actual operation, We can extract it and pass in different url addresses according to our own needs. This is left for everyone to realize by themselves.

A simple search for chestnuts:

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()

In the above code, we searched the editor's favorite anime in Baidu, hee hee, are you very happy, just learning and playing, I feel that the test is also beautiful.

Selenium can locate elements in many ways. This reader can learn on their own.

As you can see, this is the prototype of UI testing. With this prototype, we can expand it, expand it, and finally build a framework.

Add log log:

On the basis of the above, we can add the log log output during execution. So start writing the log file and put it in the comm folder as a common method. This part of the content has been introduced in the interface testing framework, so please move here for those who are not clear: https://my.oschina.net/u/3041656/blog/820023

Relevant operations to extract the browser:

We can strip out the operation of the browser and put it into a separate file, which is clear and avoids repeated code operations. And it is easier to maintain.

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()

The above is the part I stripped out and put it in a separate thread.

Does anyone feel familiar? In fact, it is the same as the principle of log. This is "inferring others from one case." Oh, the routine is that routine, it depends on how you use it.

Those things about Element:

Friends who have done UI functional testing should know that elements are the most basic and most important things in our testing, thinking that they are our direct operation objects, so, if we handle them well, we will save a lot of trouble, so what? , Next, the editor will continue to share some methods of dealing with elements by myself, I hope it can be helpful to everyone. If anyone has a better method, please be sure to tell the editor! Xiaobian thanks in advance!

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)

This is a small compilation, the methods about element that can be used at present, I feel tired and don’t like it~

But life goes on and the work is not done. So, please let me finish the rest of the code! ! !

Those annoying test data files:

Every good test is inseparable from a good test case data. So, with so much data, how can we manage it so that it is not chaotic and convenient to change and maintain the data in the future? Next, the editor will tell my friends a big news, knock on the blackboard! ! !

In fact, I don't know any good way, I just use the excel file to manage the test cases in a unified way. please look below:

The form is the form, and the content can be modified however you want. After all, I can only help you here. As for the reading of the content of the excel file, it is also described in detail in the blog post on the interface test. For those who don't understand, please move: https://my.oschina.net/u/3041656/blog/820023

In fact, come out test cases, there is a huge number of data groups, guess who they are? ? ?

Dangdang, the answer is: element positioning data, including: id, name, classname, xpath, etc. These data are the only way to find page elements during the testing process. . . So friends, you must pay attention and deal with them.

please look below:

The stupid editor uses xml files to manage it.

Does anyone else want to ask how to read xml files? Hey-hey. . . I won't tell you because I've covered it in the previous blog post! I said it! It's over! La! !

So far, today's content is over. I hope it will inspire and help everyone. Although it is a bit messy, as long as you understand these divisions and implementation methods, I believe that you can also write UI automation that you are satisfied with. test framework. So, let's do it together.

PS: There are some parts that have not been mentioned, because the content of the interface automation framework is the same as that of the previous introduction, so I will not repeat it. If you want to know more, you can move here. Thanks! https://my.oschina.net/u/3041656/blog/820023

 

This article is an original article, please indicate the original address when reprinting, thank you for your support. I hope you all work hard to grow together.


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325170273&siteId=291194637