Writing automated test scripts

demand:

  1. Reading rows from Excel (one per line API (url, request type, name, description, parameters, expected value))

  2. Use parameterized for every request, send a request to use requests, request for obtaining the results, extract fields from the results, expected to do with the asserted value,

  3. Use allure generate test reports

    1. Add a title and description for each request in Example

  4. The test report email

    1. Question: send mail, you can send folder? The answer is no,

    2. The solution is: the allure report a zip folder

    3. Send the zip file

  5. Do you think the key point in adding log on log

    1. When requested

    2. When asserted

    3. Optional when packed

    4. When read Excel

  6. To understand the coupling, software developers need to follow the specifications

    1. Data folder

    2. Configure Folder

    3. Scripts folder

    4. and many more

  7. If you have difficulty writing can be achieved in one file

Use of knowledge:

  1. requests

  2. pytest

  3. Excel spreadsheet operations

  4. send email

  5. Logging

  6. Directory application development project specification

  7. allure

    1. title knowledge

      2.description knowledge points
. First, a software development related directory specification established:

Second, the configuration settings:

os Import 
Import datetime
Import shutil
Import SYS

base_dir = os.path.dirname (os.path.dirname (os.path.abspath (__ file__)))
# Print (base_dir) #D: \ S27 \ day69 \ nb

# definition file name :
file_name = "Interface test example .xlsx"

# path splicing:
file_path = the os.path.join (base_dir, "Data", file_name)
# Print (file_path) #D: \ S27 \ day69 \ Nb \ Data \ Interface test example .xlsx

# ---------------- -------------------- related logs
# logging level
, LOG_LEVEL, = 'Debug'

# screen output stream
LOG_STREAM_LEVEL = 'Debug'

# file output stream
LOG_FILE_LEVEL = 'info'

# log file naming
LOG_FILE_NAME = os.path.join (base_dir, 'logs ', datetime.datetime.now (). strftime ('% Y-% m-% d ') +' .log ')

# Allure reports related to:
= the os.path.join report_path (base_dir, "Report")
result_path = the os.path.join (base_dir, "Report", "Result")
allure_html_path = the os.path.join (base_dir, "Report", "allure_html")
= Command "Generate Allure {} {} -o --clean" .format (result_path, allure_html_path)

# package to the root directory:
zip_case_result_path = allure_html_path

# file name to be packaged:
zip_file_name = "allure_report.zip"

# files packaged store where to go:
zip_save_path = report_path

# mailbox-related:
# third-party SMTP service
# set the server
mail_host = "smtp.qq.com"

# username
mail_user = "[email protected]"

# obtain an authorization code
mail_pass = "mpaocydzpzfjidge"

# sender account
sender = '[email protected] '

# receive mail, you can be set to your mailbox and QQ mailbox or other multiple recipients
= Receivers [ '[email protected]']

# mail subject:
Subject = 'Python example messages with attachments Send'

# message body content
send_content = 'This is today's test report, please download the attachment and use pycharm open'

# path message attachments:
send_file_path = the os.path.join (zip_save_path, zip_file_name)
send_file_name = zip_file_name

IF the __name__ == '__main__':
# Print (send_file_path)
Pass
# The os.remove (report_path)
# shutil.rmtree (report_path)
# View path :
# Print (sys.path)
# View package:
# Print (sys.modules)

Third, the configuration pytest.ini:

[pytest]
addopts = -s -v --alluredir ./report/result
testpaths = ./scripts
python_files = test_*.py
python_classes = Test*
python_functions = test_*

Four, data file Data Interface Test Example .xlsx:

Five, logs log file:
six, report report:
seven, scripts test case:

import pytest
import allure
from utils.ExcelHandler import Excel
from utils.LogHandler import logger
from utils.RequestHandler import RequestHandler
from utils.AllureHandler import AllureHandler


@pytest.mark.parametrize("d", Excel().get_excel_data())
def test_case(d):
# print(d)
result = RequestHandler(d).get_response()
# logger().info(d)
allure.dynamic.title(d["case_project"])
allure.dynamic.description("<font color='red'>请求的URL:</font>{}<hr />"
"<font color='red'>请求的类型:</font>{}<hr />"
"<font color='red'>Actual values: </ font> {} <hr /> "
"<font color = 'red' > Expected values: </ font> {} <HR />"
"" .format (D [ "case_url"],
D [ "case_method"],
Result [. 1],
Result [0 ],
))
Assert Result [0] == Result [. 1]

# DEF teardown_module ():
# = allure_obj AllureHandler ()
"" "allure generate test reports" ""
# allure_obj.execute_command ()
"" "packaged file" " "
# allure_obj.zip ()
" "" send Mail "" "
# allure_obj.send_email()

Eight, AllureHandler.py reporting:

"" " 
Execution command to generate reports allure
packaged allure report
transmitting compressed packets
" ""

Import OS
# compressed file import module
Import ZipFile
Import smtplib
Import the shutil
Import Time
from email.mime.text Import MimeText
from email.mime.multipart Import MimeMultipart
Import Header email.header from
from the conf Import Settings
from Logger utils.LogHandler Import
from Import Call The subprocess, the Popen


class AllureHandler (Object):
DEF the __init __ (Self):
"" "report empty directory, for subsequent ease of operation" ""
# the shutil .rmtree (settings.report_path)
Pass

DEF execute_command (Self):
"" "Allure command execution "" "
# the time.sleep (5)
logger () info ( "allure performed to generate reports: {}" the format (settings.command).).
# the os.system (settings.command)
command # shell = True strings can be identified:
Call (settings.command, True = the shell)

DEF ZIP (Self):
"" "packaged allure report" ""
# log:
. Logger () info ( "package file name: {}, packaged: {}". format (settings.zip_file_name , settings .zip_save_path))
# root folder you want to compress and mosaic:
base_dir = settings.zip_case_result_path
zip_file_name = settings.zip_file_name
# save the package file path:
f = zipfile.ZipFile (os.path.join (settings.zip_save_path, zip_file_name) , 'W', zipfile.ZIP_DEFLATED)
for the dir_path, dir_name, file_names in os.walk (base_dir):
# If it does not replace, began to copy from the root directory
file_path = dir_path.replace (base_dir, '')
# achieve the current folder and all the files contained
file_path = file_path and file_path + os.sep or ''
for file_name in file_names:
f .write (os.path.join (dir_path, file_name), file_path + file_name)
f.close ()

DEF SEND_EMAIL (Self):
"" "the package of documents sent to the specified mailbox allure" ""
. Logger () info ( "{is} to send a message, please wait ........" format (settings.receivers))
# third-party SMTP service
# set the server
mail_host = settings.mail_host
# username
mail_user = settings.mail_user
# obtain an authorization code
mail_pass = settings.mail_pass
# Senders account
SENDER = settings.sender
# incoming mail, can be set to your mailbox and QQ mailbox or other multiple recipients
receivers = settings.receivers
create a belt attachment # examples of
the Message MimeMultipart = ()

# outbox al
message [ 'From'] = Header ( " I sender", 'utf-8')

# recipient
message [ 'To'] = Header ( " I addressee", 'utf-8' )

# message subject
Subject = settings.subject
message [ 'the Subject'] = Header (Subject, 'UTF-. 8')

# message body content
send_content = settings.send_content
content_obj = MimeText (send_content, 'Plain', 'UTF-. 8' )
the Message.The attach (content_obj)

# 1 attachment structure, send the current file in the directory
= MimeText the ATTl (Open (settings.send_file_path, 'RB'). Read (), "Base64", "UTF-. 8")

# stream based model
att1 [ "Content-Type"] = "application / octet-stream"

# description file, the filename is the name of the annex show
the ATTl [ "the Content-Disposition"] = "attachment; filename = '{}'." the format (settings.send_file_name)
message.attach (the ATTl)

# attachment structure 2, the current transmission t2.py files in the directory
# ATT2 = MimeText (Open ( "t2.py", "RB"). Read (), "Base64", "UTF-. 8")
#
# # stream based model
# att2 [ " the Type-the Content "] =" file application / OCTET-Stream "
#
# # description file, filename is the name displayed in Annex
# att2 ["Content-Disposition"] = "attachment;filename = 't2.py'"
# message.attach(att2)

the try:
smtpObj smtplib.SMTP = ()
# 25 is the SMTP port number
smtpObj.connect (mail_host, 25)
smtpObj.login (mail_user, mail_pass)
smtpObj.sendmail (SENDER, Receivers, message.as_string ())
Logger () info. ( "{} message was successfully sent to the" .format (settings.receivers))
the except smtplib.SMTPException AS E:
. Logger () error ( "} {send the message to the failed possible reasons: {}". format (settings . receivers, e))

Nine, ExcelHandler.py file table functions:

import xlrd
from conf import settings
from utils.LogHandler import logger

class Excel(object):
def get_excel_data(self):
"""获取excel表格数据"""
logger().info("读取Excel表格{} {}".format(settings.file_name,settings.file_path))
book = xlrd.open_workbook(filename=settings.file_path)
sheet = book.sheet_by_index(0)
# print(sheet.nrows) #8
title = sheet.row_values(0)
l = []
for row in range(1, sheet.nrows):
# print(sheet.row_values(row))
l.append(dict(zip(title, sheet.row_values(row))))
# print(l)
return l

if __name__ == '__main__':
Excel().get_excel_data()

Ten, LogHandler.py log function:

import logging
from conf import settings

class LoggerHandler:
""" 日志操作 """
_logger_level = {
'debug': logging.DEBUG,
'info': logging.INFO,
'warning': logging.WARNING,
'error': logging.ERROR,
'critical': logging.CRITICAL
}
def __init__(self, log_name, file_name, logger_level, stream_level='info', file_level='warning'):
self.log_name = log_name
self.file_name = file_name
self.logger_level = self._logger_level.get(logger_level, 'debug')
self.stream_level = self._logger_level.get(stream_level, 'info')
= self._logger_level.get self.file_level (file_level, 'warning')
# create a log objects
self.logger = logging.getLogger (self.log_name)
# Set the log level
self.logger.setLevel (self.logger_level)
IF not Self. logger.handlers:
# set the log output stream
f_stream = logging.StreamHandler ()
f_file = logging.FileHandler (self.file_name)
# set the output stream level
f_stream.setLevel (self.stream_level)
f_file.setLevel (self.file_level)
# set the log output format
Formatter = logging.Formatter (
"% (the asctime) S% (name) S% (levelname) S% (Message) S"
)
f_stream.setFormatter(formatter)
f_file.setFormatter(formatter)
self.logger.addHandler(f_stream)
self.logger.addHandler(f_file)
@property
def get_logger(self):
"""伪装成属性返回logger对象"""
return self.logger

def logger(log_name='接口测试'):
return LoggerHandler(
log_name=log_name,
logger_level=settings.LOG_LEVEL,
file_name=settings.LOG_FILE_NAME,
stream_level=settings.LOG_STREAM_LEVEL,
file_level=settings.LOG_FILE_LEVEL
).get_logger

if __name__ == '__main__':
logger().debug('aaaa')
Log (). Info ( 'aaaa')
logger().warning('aaaa')

Eleven, RequestHandler.py request function:

import requests
import json
from utils.LogHandler import logger
from bs4 import BeautifulSoup


class RequestHandler(object):
def __init__(self, d):
self.d = d

def get_response(self):
"""获取请求结果"""
return self.send_msg()

def _response_application(self, response):
"""校验json类型的返回"""
response = response.json()
expect = json.loads(self.d.get("case_expect"))
for k in expect:
if expect[k] != response.get(k, "没有这个key:{}".format(k)):
return {k: expect[k]}, {k: response.get(k, "没有这个key:{}".format(k))}
return {k: expect [k] }, {k: response.get (k, " this does not Key: {}" the format (K).)}

DEF _response_text (Self, Response):
"" "text type of check return "" "
# response.title ()
Soup = BeautifulSoup (response.text," html.parser ")
title = soup.find (name =" title "). text
# Print (title.text)
Logger (). info ( "text type of request result, the expected value: {} | actual value: {}" the format (self.d.get ( "case_expect"), title).)
return title, self.d.get ( "case_expect")

send_msg DEF (Self):
"" "requesting" ""
Logger () info ( "request URL: {}, type: {}".. format ( self.d.get ( "case_url"), self.d. get ( "case_method")))
response = requests.request(
method=self.d.get("case_method"),
url=self.d.get("case_url"),
# params=self._check_params(),
# data=self._check_data()
)
header = response.headers["Content-Type"].split("/", 1)[0]
# header = _response_application
if hasattr(self, "_response_{}".format(header)):
a = getattr(self, "_response_{}".format(header))
result = a(response)
logger().info("预期值:{} 实际值:{}".format(result[0], result[1]))
return result

def _check_params(self):
"""检查请求参数"""
params = self.d.get("case_params")
if params:
return {}
else:
return {}

def _check_data(self):
""" 检查请求参数 """
params = self.d.get("case_params")
if params:
return {}
else:
return {}

if __name__ == '__main__':
# r1 = requests.get("https://www.cnblogs.com/Neeo/articles/10951734.html")
# print(r1.text)
# print(r1.headers)
# print(r1.title)
pass
# r2 = requests.get("https://www.v2ex.com/api/site/info.json")
# print(r2.headers)

# r3 = requests.post("https://cnodejs.org/api/v1/message/mark_all")
# print(r3.headers)

Twelve, run.py program execution entrance:

import shutil
import pytest
from utils.AllureHandler import AllureHandler
from conf import settings

if __name__ == '__main__':
pytest.main()
# shutil.rmtree(r"D:\s27\day69包含log日志功能\nb\report")
a = AllureHandler()
a.execute_command()
a.zip()
a.send_email()

Thirteen, to show the effect of:

 

 

Guess you like

Origin www.cnblogs.com/zhang-da/p/12305082.html