当前位置:网站首页>Selenium+pytest automated test framework practice

Selenium+pytest automated test framework practice

2022-07-06 09:00:00 Automated test seventh uncle

Preface

Today, I want to talk with you selenium automation + pytest The test framework , In this article, you need to know something python Basics —— At least understand classes and objects , Encapsulation inheritance ; definite selenium Basics . This article will not selenium, No, you can see it yourself selenium Chinese Translation Network .

 

One 、 Introduction to test framework

What are the advantages of a testing framework

    • High code reuse rate , If you don't use a framework , The code will be redundant
    • You can assemble logs 、 The report 、 Some advanced functions such as email
    • Improve the maintainability of data such as elements , When the elements change , Just update the configuration file
    • Use more flexible PageObject Design patterns
  • The overall directory of the test framework
  • Catalog / Whether the document description is python package common This package contains common general classes , If reading the configuration file is config The profile directory is logs Log directory page Yes selenium The depth of packaging is page_element Page element storage directory page_object Page object POM Design patterns ,TestCase All test case sets are utils The tool class is script Script files conftest.pypytest Glue files pytest.inipytest The configuration file , Such a simple frame structure is clear .

Knowing all this, let's start !

In the project, we first follow the above framework guidelines , Build every directory .

Be careful :python The package is yes , You need to add one __init__.py File to identify this directory as a python package .

Two 、 Manage time

First of all , Because many of our modules use time stamps , Or date string , So let's encapsulate time into a module .

Then let other modules call . stay utils New directory times.py modular

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import time
import datetime
from functools import wraps


def timestamp():
    """ Time stamp """
    return time.time()


def dt_strftime(fmt="%Y%m"):
    """
    datetime Format time 
    :param fmt "%Y%m%d %H%M%S
    """
    return datetime.datetime.now().strftime(fmt)


def sleep(seconds=1.0):
    """
     Sleep time 
    """
    time.sleep(seconds)


def running_time(func):
    """ Function run time """

    @wraps(func)
    def wrapper(*args, **kwargs):
        start = timestamp()
        res = func(*args, **kwargs)
        print(" Check element done! when %.3f second !" % (timestamp() - start))
        return res

    return wrapper


if __name__ == '__main__':
    print(dt_strftime("%Y%m%d%H%M%S"))

3、 ... and 、 Add configuration file

Configuration files are an essential part of the project !

Centralize fixed information in fixed files

3.1conf.py

There should be a file in the project to manage the overall Directory , I'm here, too python This file is set in the project .

In the project config directories creating conf.py file , All directory configuration information is written in this file .

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import os
from selenium.webdriver.common.by import By
from utils.times import dt_strftime


class ConfigManager(object):
    #  Project directory 
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

    #  Page element directory 
    ELEMENT_PATH = os.path.join(BASE_DIR, 'page_element')

    #  The report file 
    REPORT_FILE = os.path.join(BASE_DIR, 'report.html')

    #  The type of element location 
    LOCATE_MODE = {
        'css': By.CSS_SELECTOR,
        'xpath': By.XPATH,
        'name': By.NAME,
        'id': By.ID,
        'class': By.CLASS_NAME
    }

    #  Email messages 
    EMAIL_INFO = {
        'username': '[email protected]',  #  Switch to your own address 
        'password': 'QQ Email authorization code ',
        'smtp_host': 'smtp.qq.com',
        'smtp_port': 123
    }

    #  The recipient 
    ADDRESSEE = [
        '[email protected]',
    ]

    @property
    def log_file(self):
        """ Log directory """
        log_dir = os.path.join(self.BASE_DIR, 'logs')
        if not os.path.exists(log_dir):
            os.makedirs(log_dir)
        return os.path.join(log_dir, '{}.log'.format(dt_strftime()))

    @property
    def ini_file(self):
        """ The configuration file """
        ini_file = os.path.join(self.BASE_DIR, 'config', 'config.ini')
        if not os.path.exists(ini_file):
            raise FileNotFoundError(" The configuration file %s non-existent !" % ini_file)
        return ini_file


cm = ConfigManager()
if __name__ == '__main__':
    print(cm.BASE_DIR)

Be careful :QQ How to generate email authorization code? Go to Baidu by yourself

This conf I copied the file Django Of settings.py The setting style of the file , But there are some differences .

In this file, we can set our own directories , You can also view your current directory .

Followed the agreement : Invariant constant names are all capitalized , Function names are lowercase . It looks beautiful as a whole .

3.2config.ini

In the project config Create a new directory config.ini file , For the time being, we need to put what we need to test URL

[HOST]
HOST = https://www.baidu.com

Four 、 Read configuration file

The configuration file is created , Next, we need to read the configuration file and use the information in it .

We are common Create a new one in the directory readconfig.py file

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import configparser
from config.conf import cm

HOST = 'HOST'


class ReadConfig(object):
    """ The configuration file """

    def __init__(self):
        self.config = configparser.RawConfigParser()  #  When there is % Please use the symbol of Raw Read 
        self.config.read(cm.ini_file, encoding='utf-8')

    def _get(self, section, option):
        """ obtain """
        return self.config.get(section, option)

    def _set(self, section, option, value):
        """ to update """
        self.config.set(section, option, value)
        with open(cm.ini_file, 'w') as f:
            self.config.write(f)

    @property
    def url(self):
        return self._get(HOST, HOST)


ini = ReadConfig()

if __name__ == '__main__':
    print(ini.url)

You can see that we use python Built in configparser The module of config.ini The file was read .

about url Extraction of values , I used higher-order grammar @property Property value , It's easier to write .

5、 ... and 、 Record operation log

journal , Everyone should be familiar with the term , Is to record the actions in the code .

stay utils Create a new logger.py file .

This file is what we use to record some operation steps in the process of automated testing .

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import logging
from config.conf import cm


class Log:
    def __init__(self):
        self.logger = logging.getLogger()
        if not self.logger.handlers:
            self.logger.setLevel(logging.DEBUG)

            #  Create a handle write file 
            fh = logging.FileHandler(cm.log_file, encoding='utf-8')
            fh.setLevel(logging.INFO)

            #  Create a handle Output to console 
            ch = logging.StreamHandler()
            ch.setLevel(logging.INFO)

            #  Define the format of the output 
            formatter = logging.Formatter(self.fmt)
            fh.setFormatter(formatter)
            ch.setFormatter(formatter)

            #  Add to handle
            self.logger.addHandler(fh)
            self.logger.addHandler(ch)

    @property
    def fmt(self):
        return '%(levelname)s\t%(asctime)s\t[%(filename)s:%(lineno)d]\t%(message)s'


log = Log().logger

if __name__ == '__main__':
    log.info('hello world')

Run the file in the terminal , You can see that the command line prints out :

INFO	2022-06-15 16:00:05,467	[logger.py:38]	hello world

And then in the project logs The log file of the current month is generated under the directory .

6、 ... and 、 Simple understanding POM Model

Because we'll talk about elements related , So first understand POM Model

Page Object Mode has the following advantages .

This view comes from 《Selenium automated testing —— be based on Python Language 》

  • Abstracting out objects can minimize the impact of developers modifying page code on testing , therefore , You just need to page
    Adjust to the elephant , It has no effect on the test ;
  • You can reuse part of the test code in multiple test cases ;
  • Test code becomes more readable 、 flexible 、 Maintainable

Page Object Pattern

 

  • basepage ——selenium Base class of , Yes selenium To encapsulate
  • pageelements—— Page elements , Extract the page elements separately , Put it in a file
  • searchpage —— Page object class , hold selenium Methods and page elements
  • testcase —— Use pytest For integration searchpage Write test cases

We can see from the picture above , adopt POM Model thinking , We put :

  • selenium Method
  • Page elements
  • Page object
  • The test case

The above four code bodies are split , Although doing it with few use cases will increase the code , But when there are many use cases, it makes a lot of sense , The amount of code will decrease significantly as use cases increase . Our maintenance code becomes more intuitive and obvious , Code readability has also become much better than factory mode , The code reuse rate has also been greatly improved .

This article is here for the time being , I'll talk about it later .

 

原网站

版权声明
本文为[Automated test seventh uncle]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/187/202207060856582385.html