How does python parse a configuration file and apply it to a project

  • 2021-07-03 00:16:07
  • OfStack

Type of configuration file

Typically, configuration files in automated tests are files with. ini and. conf suffixes

Composition of configuration file

1.section

2.option

3.value

Format of configuration file


[section_name]
# = Number can be replaced by: number 
option_name=value

Comments for configuration files

Usually use # or; Semicolon comments, one point to note, it is best not to write comments at the end of option_name=value, or you will encounter unexpected errors

The role of configuration files

So what does our configuration file mainly do?

1. You can store test data used by test cases in your tests

2. It can store the resource data used in the test, such as database address, user, password and so on

3. It can be used as an ui object library to store the page element information in our ui automated test project

4. You can store the global variables used by the project, such as the root directory of the project, the path of the log, the report, and so on

The above data can be stored in the configuration file, convenient for us to read, when the project 1 configuration information changes, we only need to modify the configuration file, without modifying the specific code, greatly reducing the maintenance cost of the project!

ok, now that I'm clickbait title, I'll tell you how to apply 1 minute to the project. If we have a configuration file, we must parse the file first. We now have such a configuration file, which stores the following contents


[126mail_login]
loginPage.frame=xpath>//div[@id='loginDiv']/iframe
loginPage.username=xpath>//input[@name='email']
loginPage.password=xpath>//input[@name='password']
loginPage.loginBtn=xpath>//a[@id='dologin']
[126mail_homePage]
homePage.addressbook=id>_mail_tabitem_1_4text
[126mail_addContactPage]
addContactPage.newContact=xpath>//span[text()=' New Contact ']
addContactPage.newName=id>input_N
addContactPage.newMail=xpath>//div[@id='iaddress_MAIL_wrap']//input[@class='nui-ipt-input']
addContactPage.newMark=xpath>//span[@class='nui-chk-text']/preceding-sibling::span/b
addContactPage.newPhone=xpath>//div[@id='iaddress_TEL_wrap']//input[@class='nui-ipt-input']
addContactPage.newComment=id>input_DETAIL
addContactPage.newCommit=xpath>//span[text()=' Indeed   Fixed ']

Encapsulation code

The following encapsulation, which I wrote earlier, is not a very general function, but it will be completely applicable if your configuration file and my example above are used to store ui object library.


"""
------------------------------------
@Time : 2019/5/16 10:56
@Auth : linux Super 
@File : ParseConfigOld.py
@IDE : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
------------------------------------
"""
from configparser import (
ConfigParser,
NoSectionError,
NoOptionError
)
filename = 'configfile.ini'
class ParseConfigFile(object):
"""
 Analyse ini Configuration file 
"""
def __init__(self):
try:
self.cf = ConfigParser() #  Getting Profile Objects 
self.cf.read(filename, encoding='utf-8') #  Load configuration file into memory 
except Exception as e:
raise e
def getItemsSection(self, section):
"""
 Get section All of the following section Key value of 
:param sectionName:
:return:
"""
try:
value = dict(self.cf.items(section))
except (NoSectionError, KeyError):
print('{} not exit'.format(section))
except Exception as e:
raise e
else:
return value
def getElementValue(self, section, option):
""" Modify this part of the code according to your own needs """
try:
#  My configuration file is divided by this symbol, and all parsing should use this symbol to divide and get elements 
locator = self.cf.get(section, option).split('>')
except (NoSectionError, NoOptionError, KeyError):
print('section:{} or option:{} not exit'.format(section, option))
except Exception as e:
raise e
else:
return locator #  Get option Key corresponds to value
def getAllSections(self):
try:
all_sections = self.cf.sections()
except Exception as e:
raise e
else:
return all_sections #  All sections The return value is a list 
if __name__=='__main__':
cf = ParseConfigFile()
locator = cf.getElementValue('126mail_login','loginPage.username')
print(locator)
print(cf.getItemsSection('126mail_login'))
print(cf.getAllSections())

Packaging improvement

The following encapsulation can complete data parsing of any data type stored in the configuration file in almost any automated test project


"""
------------------------------------
@Time : 2019/5/16 9:11
@Auth : linux Super 
@File : ParseConfigFile.py
@IDE : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
------------------------------------
"""
from configparser import (
ConfigParser,
NoOptionError,
NoSectionError
)
class ParseConfigFile(ConfigParser):
def __init__(self, filename):
super().__init__()
try:
self.filename = filename
self.read(filename, encoding='utf-8')
except Exception as e:
raise e
def get_all_option(self, section='DEFAULT'):
""" Gets the specified section Under all of them option"""
try:
options = self.options(section)
return options
except NoSectionError:
print('NoSectionError : {} not exist'.format(section))
except Exception as e:
raise e
def get_value(self, section='DEFAULT'):
""" Gets the specified section All of the option And value , return 1 A dictionary """
try:
value = dict(self.items(section))
return value
except (NoSectionError, KeyError):
print('{} not exist'.format(section))
except Exception as e:
raise e
def get_option_value(self, section, option, flag=False):
"""
 Gets the specified section And option Corresponding data 
 If option If the corresponding data is a number, it is automatically converted to int Or float
 If option The corresponding data is a data that can be used eval The type of conversion is passed, the flag For True Automatically convert when , Otherwise output str
"""
try:
value = self.get(section, option)
if value.isdigit():
return int(value)
try:
return float(value)
except Exception:
pass
if isinstance(flag, bool) and flag:
return eval(value)
return value
except (NoSectionError, NoOptionError, KeyError):
print('no option "{}" or section "{}"'.format(option, section))
except Exception as e:
raise e
def __call__(self, section='DEFAULT', option=None, flag_eval=False, flag_bool=False):
"""
 This method is called by default when the object is used as a function 
 This method can achieve most of the above functions 
:param section:
:param option:
:param flag_eval:  If is True  We use eval Conversion type 
:param flag_bool:  If is True  We use converting data into bool
:return:
"""
if option is None:
return dict(self[section])
if isinstance(flag_bool, bool):
if flag_bool:
return self.getboolean(section, option)
else:
raise ValueError('{} must be type bool'.format(flag_bool))
data = self.get(section, option)
if data.isdigit():
return int(data)
try:
return float(data)
except Exception:
pass
if isinstance(flag_eval, bool):
if flag_eval:
return eval(data)
else:
raise ValueError('{} must be type bool'.format(flag_eval))
return data
if __name__ == '__main__':
conf = ParseConfigFile('configfile.ini')
print(' All option', conf.get_all_option('FilePath'))
print(' Get section:{},option:{} Corresponding data :{}'.
format('FilePath', 'TestCase', conf.get_option_value('FilePath', 'TestCase')))
print(' Get section:{} Under all key values {}'.format('FilePath', conf.get_value('ExcelNum')))
print(conf())
print(conf(section='FilePath', option='TestCase'))
print(conf(option='a', flag_bool=True))
print(conf(section='ExcelNum', option='Actual_Column_Num', flag_eval=True))

1 minute applied to the project

What? You still don't know how to apply 1 minute to the project.

Well, it seems that there is no escape. I'm going to say... first copy the code, of course you already know the meaning of the above code, create a new py file in your project, copy the code into your file, ok, and then you may already know how to use it. Can this last for 1 minute?


Related articles: