selenium+python for web-side automated test framework and case-based detailed tutorial

Recently suffered a 10,000-point attack, due to problems in the company's business, less heavy work tasks, time to explore selenium+python automated testing, combined with the information found on the Internet to write their own framework for web automated testing, as I am also just beginning to learn python, this automation framework has been basically completed so summarize the gains and losses of writing, easy to useLooking back at the review later, there are many deficiencies, but also encountered a variety of strange flower problems, I hope the gods will teach more.

First, we need to understand what automated testing is, simply write code, script, let the software run automatically, find defects, replace some manual testing.After learning about automated testing, we need to understand which modules a framework needs to be divided into:

 

The framework shown above is suitable for most automated tests, such as web UI and interface automated tests. If the big guys have a good way to do this, please teach me more about each module below:

  • Common: store some common methods
  • data: store some file information
  • logs: log information written in the stored program
  • picture: store screenshot file information in program
  • report: store test reports
  • test_case: Stores and writes specific test cases
  • conf.ini, readconf.py: Stores written configuration information

Here's what each module is about: conf.ini stores information that won't be easily changed. The code you write is as follows:

[DATABASE]
host = 127.0.0.1
username = root
password = root
port = 3306
database = cai_test

[HTTP]
# Interface url
baseurl = http://xx.xxxx.xx
port = 8080
timeout = 1.0
readconf.py Files are mainly for reading conf.ini Data information in
# *_*coding:utf-8 *_*
__author__ = "Test Lu"
import os,codecs
import configparser














prodir = os.path.dirname(os.path.abspath(__file__))
conf_prodir = os.path.join(prodir,'conf.ini')
class Read_conf():
def __init__(self):
with open(conf_prodir) as fd:
data = fd.read()
#Empty file information
if data[:3] ==codecs.BOM_UTF8:
data = data[3:]
file = codecs.open(conf_prodir,'w')
file.write(data)
file.close()
self.cf = configparser.ConfigParser()
self.cf.read(conf_prodir)
def get_http(self,name):
value = self.cf.get("HTTP",name)
return value

def get_db(self,name):
return self.cf.get("DATABASE",name)
Note here that python3.0 The above version and python2.7 Edition import configparser There are some differences in the approach
Read some configuration collections and you're done. Here's how common Public files under packages




















End from top to bottom now!common is primarily a way of encapsulating some positioning elements:

# *_*coding:utf-8 *_*
__author__ = "Test Lu"
from selenium import webdriver
import time,os
import common.config
# from common.logs import MyLog
project_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
class Comm(object):
def __init__(self,driver):
self.driver = driver
# self.driver = webdriver.Firefox()
self.driver = webdriver.Chrome()
self.driver.maximize_window()
def open_url(self,url):
self.driver.get(url)
self.driver.implicitly_wait(30)
# selenium Location Method
def locate_element(self,loatetype,value):
if (loatetype == 'id'):
el = self.driver.find_element_by_id(value)
if (loatetype == 'name'):
el = self.driver.find_element_by_name(value)
if (loatetype == 'class_name'):
el = self.driver.find_element_by_class_name(value)
if (loatetype == 'tag_name'):
el = self.driver.find_elements_by_tag_name(value)
if (loatetype == 'link'):
el = self.driver.find_element_by_link_text(value)
if (loatetype == 'css'):
el = self.driver.find_element_by_css_selector(value)
if (loatetype == 'partial_link'):
el = self.driver.find_element_by_partial_link_text(value)
if (loatetype == 'xpath'):
el = self.driver.find_element_by_xpath(value)
return el if el else None
# selenium click
def click(self,loatetype,value):
self.locate_element(loatetype,value).click()
#selenium input
def input_data(self,loatetype,value,data):
self.locate_element(loatetype,value).send_keys(data)
#Gets the specified element located
def get_text(self, loatetype, value):
return self.locate_element(loatetype, value).text
# Get tag properties
def get_attr(self, loatetype, value, attr):
return self.locate_element(loatetype, value).get_attribute(attr)
# Screenshot of Page
def sc_shot(self,id):
for filename in os.listdir(os.path.dirname(os.getcwd())) :
if filename == 'picture':
break
else:
os.mkdir(os.path.dirname(os.getcwd()) + '/picture/')
photo = self.driver.get_screenshot_as_file(project_dir + '/picture/'
+ str(id) + str('_') + time.strftime("%Y-%m-%d-%H-%M-%S") + '.png')
return photo
def __del__(self):
time.sleep(2)
self.driver.close()
self.driver.quit()
Below, config Files are mainly used to read information from files:




























































import os,xlrd
from common.logs import MyLog
from xml.etree import ElementTree as ElementTree
mylogger = MyLog.get_log()
project_dir = os.path.dirname(os.getcwd())

def user_Add():
'''excel Read user login information in file'''
with xlrd.open_workbook(project_dir+'/data/test_data.xlsx') as files:
table_user = files.sheet_by_name('userdata')
try:
username = str(int(table_user.cell(1,0).value))
except:
username = str(table_user.cell(1,0).value)
try:
passwd = str(int(table_user.cell(1,1).value))
except:
passwd = str(table_user.cell(1,1).value)
try:
check = str(int(table_user.cell(1, 2).value))
except Exception:
check = str(table_user.cell(1, 2).value)
table_url = files.sheet_by_name('base_url')
base_url = str(table_url.cell(1,0).value)
return (username,passwd,base_url,check)

#Read information from xml files, define a global dictionary to access information read by xml
database={}
def set_read_xml():
sql_path = os.path.join(project_dir,'data','SQL.xml')
data =ElementTree.parse(sql_path)
for db in data.findall('database'):
name = db.get('name')
table = {}
for tb in db.getchildren():
table_name = tb.get("name")
sql = {}
for data in tb.getchildren():
sql_id = data.get("id")
sql[sql_id] = data.text
table[table_name] = sql
database[name] = table
mylogger.info("Read xml File information%s" %database)
def get_sql_sen(database_name,table_name,sql_id):
set_read_xml()
db = database.get(database_name).get(table_name)
if db.get(sql_id):
sql = db.get(sql_id).strip()
mylogger.info("Return sql Statement Information%s" % sql)
return sql
else:
mylogger.info("The information checked is empty,Wrong parameters passed!Database name: [%s],Table Information [%s],Queried id[%s]"
%(database_name,table_name,sql_id))

Next comes the simplest log logs.py Modular:





















































# logging Module allows us to customize encapsulation of a new log class
import logging,time
import os.path
class Logger(object):
def __init__(self, logger,cases="./"):
self.logger = logging.getLogger(logger)
self.logger.setLevel(logging.DEBUG)
self.cases = cases
# Create a handler,Used for writing log files
for filename in os.listdir(os.path.dirname(os.getcwd())):
if filename == "logs":
break
else:
os.mkdir(os.path.dirname(os.getcwd())+'/logs')
rq = time.strftime('%Y%m%d%H%M', time.localtime(time.time()))
log_path = os.path.dirname(os.getcwd()) + '/logs/'
log_name = log_path + rq + '.log' # file name
# Write logs to disk
fh = logging.FileHandler(log_name)
fh.setLevel(logging.INFO)
# Create a handler,For output to console
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
# Definition handler Output format of
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
# Add handler to logger
self.logger.addHandler(fh)
self.logger.addHandler(ch)
def getlog(self):
return self.logger

common Last module is test_runner.py This method is primarily used to execute all test cases
































import time,HTMLTestRunner
import unittest
from common.config import *
project_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),os.pardir))
class TestRunner(object):
''' Execute Test Case '''
def __init__(self, cases="../",title="Auto Test Report",description="Test case execution"):
self.cases = cases
self.title = title
self.des = description
def run(self):
for filename in os.listdir(project_dir):
if filename == "report":
break
else:
os.mkdir(project_dir+'/report')
# fp = open(project_dir+"/report/" + "report.html", 'wb')
now = time.strftime("%Y-%m-%d_%H_%M_%S")
# fp = open(project_dir+"/report/"+"result.html", 'wb')
fp = open(project_dir+"/report/"+ now +"result.html", 'wb')
tests = unittest.defaultTestLoader.discover(self.cases,pattern='test*.py',top_level_dir=None)
runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title=self.title, description=self.des)
runner.run(tests)
fp.close()
That's it common All modules of a public module, to put it simply, there are problems writing these public modules, especially reading them xml File, oh!For a python Small white is so sour!Next db The content of the module, db Modules are primarily read sql Statement and return the corresponding value!























import pymysql
import readconf
import common.config as conf
readconf_conf = readconf.Read_conf()

host = readconf_conf.get_db("host")
username = readconf_conf.get_db("username")
password = readconf_conf.get_db("password")
port = readconf_conf.get_db("port")
database = readconf_conf.get_db("database")
config_db = {
'host': str(host),
'user': username,
'password': password,
'port': int(port),
'db': database
}
class Mysql_DB():
def __init__(self):
'''Initialize database'''
self.db = None
self.cursor = None
def connect_db(self):
'''Create Connected Database'''
try:
self.db = pymysql.connect(**config_db)
#Create Cursor Location
self.cursor = self.db.cursor()
# print("Successfully linked database")
conf.mylogger.info("link IP by%s Of%s Database Success" %(host,database))
except ConnectionError as ex:
conf.mylogger.error(ex)

def get_sql_result(self,sql,params,state):
self.connect_db()
try:
self.cursor.execute(sql, params)
self.db.commit()
# return self.cursor
except ConnectionError as ex:
self.db.rollback()
if state==0:
return self.cursor.fetchone()
else:
return self.cursor.fetchall()
def close_db(self):
print("close database")
conf.mylogger.info("close database")
self.db.close()
Start writing db Module is a module that always transmits the information of the dictionary module to the data link. Query a lot of data on the Internet to thoroughly solve it. It is also an improvement for yourself. Ha-ha, here is the pit you tread on to help you learn later.**config_db Pass in the dictionary as a key parameter,
The following examples illustrate:
If kwargs={'a':1,'b':2,'c':3}that**kwargs This is equivalent to test(a=1,b=2,c=3)Is it easy?Ha-ha

These are the main modules of the framework. Every project of other modules is different from each system. Here is the list, because you can't reuse them even if you write them out. Here's to show you what other modules Xiao Bai has.




















































 

Have a look at the xml module under the data module that you may use, then post it to everyone!Because ui tests mainly use select and delete statements, they also do not write very complex sql statements

<?xml version="1.0" encoding="utf-8" ?>
<data>
<database name="database_member">
<table name="table_member">
<sql id="select_member">
select * from user where real_name=%s
</sql>
<sql id="select_member_one">
select mobile from user where mobile=%s
</sql>
<sql id="delete_member">
delete from user where mobile=%s
</sql>
<sql id="insert_member">
insert into user(id) value(%s)
</sql>
<sql id="update_member">
uodate user set real_name = %s where uuid=%s
</sql>
</table>
</database>
</data>

The following describes the contents of other modules: The test_data.xlsx file mainly stores some user information and url information, so modifying user information and url information does not need to modify the code for easy operation later!logs are log information generated when the code is run, pictures store picture information, and reports store input report information.
Test_case is a module that writes users. All use case names need to start with test, because unittest automatically matches the.py file that starts with all tests under the test_case folder when testing.





















Above is the UI automation framework written by Xiaobian. This is also the first time that Xiaobian has written this kind of blog. Please mark the source for reprinting. Thank you.Favorite friends can also give Xiaobian a compliment, I will continue to study hard and grow up with you!


 








Tags: SQL Database xml Selenium

Posted on Wed, 08 Apr 2020 20:10:11 -0700 by adnan1983