The second Python selenium automated test project

preface

The previous article said that I want to write an article on automatic combat. I'm busy during this period. I haven't updated my blog since I went home for 11. Today, I'll sort out the code of the actual combat project for everyone to learn. (Note: the project is a test of our company's internal system, which can only be accessed through the internal network, but not through the external network)

Q:

1. The external network cannot be accessed and the code cannot run. It depends on the use of this project

2. How to learn this project

3. How to learn automated testing (python+selenium)

Answer:

1. In fact, the code is not important. I hope that after reading the project completely, you will have ideas and ideas, learn the framework structure and design ideas of the project, and apply them to your own project, then the purpose will be achieved (some public methods involved in the project can be run separately, and you can use them to implement them in your own project)

2. First of all, I hope you will learn this project with your goals. 1 Directory structure of the project (what is stored in each directory) 2 How to use the framework in the project (the unittest framework is used in this project) 3 How is the design pattern applied in this project (page object design pattern is applied in this project)

3. Personally

1) If you don't have any programming foundation, it is recommended to learn a programming language first, including the construction of the environment, write your own code, think more and think more when you encounter problems, which will certainly deepen your impression. If you have a certain programming foundation, it's ok to directly look at the basic syntax of python and selenium (my experience in automation testing is also limited, and I may not give you too many suggestions. Of course, the more, the better!)

2) Build a framework by yourself and write a practical project by hand. At this time, you will find that you still have a lot of things you can't do. Then the line will come. Learn where you can't do it. Learn and write while you learn. Until your project is completed, you will find that you can do a lot better. Of course, there are more things you can't do. Because your thinking is slowly broadened, you will think of unattended, integration and so on

3) You can participate in the training of training institutions. To be honest, there are more and more training institutions now. Personally, I think the teachers in some institutions are really of low standard, because they teach the foundation and don't have much advanced content, but one thing is good. You can systematically learn a series of automation knowledge

ok said a lot of nonsense, don't mind! Direct project

Project introduction

Project Name: * * company e-retail membership system

Project purpose: to realize the automatic test execution of e-retail member system project

Project version: v1.0 0

Project directory

Retail_TestPro
    Docs# Store relevant documents of the project
        01 test plan
        02 Test outline
        03 test case
        04 Test report
        05 Test progress
        06 Technical documentation
        07 Test application
    Package# Store third-party plug-ins
        HTMLTestRunner.py
    Retail            
        Config
            __init__.py
            Conf.py# Read the configuration file, get the project and directory path, and get the path of all directory files to be used
            Config.ini# The path where the project and directory are stored
        Data
            TestData
                __init__.py
                elementDate.xlsx# Store all element information and test data in the project
                Email_receiver.txt# Store the recipient information of the mail
        Report# Test report
            Image
                Fail# Save screenshot of case execution failure
                Pass# Save the screenshot when the use case is executed successfully
            Log# Store the log information during the execution of the use case
            TestReport# Store the test report generated after the execution of the test case
        Test_case# Test case information
            Models # Store some public methods
                Doconfini.py# read configuration file
                Doexcel.py# Read excel file
                Driver.py# Store driver
                Log.py# Generate log
                Myunit.py# Inherit unittest Testcase
                Sendmail.py# Send mail
                Strhandle.py# string manipulation
                Tcinfo.py# Basic information of test case
                Testreport.py# Test report
            Page_obj# Test module
                Activerule_page.py
                Base_page.py
                Company_page.py
                Createrule_page.py
                Memberquery_page.py
                Modifypw_page.py
                Pointquery_page.py
                ActiveRuleTc.py
                CompanyQueryTc.py
                CreateRuleTc.py
                LoginTc.py
                MemberQueryTc.py
                ModifyPwTc.py
                PointQueryTc.py
        runTc.py# Execute test cases             

Environmental projects

This edition

python 36

pip insatll selenium

PyCharm 2017.2.4
Windows 10 10.0

HTMLTestRunner.py

Project framework

unittest unit test framework

pageobject design pattern

UI object library idea

Project design

1. A module (the page of the tested item) corresponds to a py file and a test class (test file)

2. Each test page (page of the system) stores page elements and functions involved in this page

3. Each use case is combined into a test class to generate a py file

Project objectives

When we write the automation test project, we must think about the functions of your script, whether we need to modify the script in large quantities when the page elements are changed, and whether we also need to modify the script when testing different data. Then we can think of these initial goals

  1. Generate test case execution result report

2. Generate test case execution log

3. Use case execution fails or automatically sends email report after execution

  1. Capture the picture when the use case fails or succeeds

5. Data driven (read test data and reduce script maintenance cost)

Project code

config.ini # storage project and path

[project]
project_path = D:\Petrochina_Retail_Test_Project


elementData.xlsx # stores all test data and elements

An excel file. It's not convenient to post the content inside (go ahead first, never mind what's inside. Ha ha, look for it later)

mail_receiver.txt # stores the account number of the mail recipient. Multiple accounts can be added and divided by ','

**@qq.com 

The public method models the following files:

doconfini.py

 '''
 2 Code description: read conf file
 3 Create time: 
 4 Developer: 
 5 '''
 6 
 7 import logging
 8 import configparser
 9 from retail.config.conf import *
10 from retail.test_case.models.log import Logger
11 
12 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)
13 class DoConfIni(object):
14 
15     def __init__(self):
16         """
17 
18         :param filename:
19         """
20         self.cf = configparser.ConfigParser()
21     
22     # Read data from ini file
23     def getConfValue(self,filename,section,name):
24         """
25 
26         :param config:
27         :param name:
28         :return:
29         """
30         try:
31             self.cf.read(filename)
32             value = self.cf.get(section,name)
33         except Exception as e:
34             log.logger.exception('read file [%s] for [%s] failed , did not get the value' %(filename,section))
35             raise e
36         else:
37             log.logger.info('read excel value [%s] successed! ' %value)
38             return value
39     # Write data to ini file
40     def writeConfValue(self,filename, section, name, value):
41         """
42 
43         :param section: section
44         :param name: value name
45         :param value:  value
46         :return: none
47         """
48         try:
49             self.cf.add_section(section)
50             self.cf.set(section, name, value)
51             self.cf.write(open(filename, 'w'))
52         except Exception :
53             log.logger.exception('section %s has been exist!' %section)
54             raise configparser.DuplicateSectionError(section)
55         else:
56             log.logger.info('write section'+section+'with value '+value+' successed!')
57 
58 if __name__ == '__main__':
59     file_path = currPath
60     print(file_path)
61     read_config = DoConfIni()
62 
63     value = read_config.getConfValue(os.path.join(currPath,'config.ini'),'project','project_path')
64     print(value)
65 
66     read_config.writeConfValue(os.path.join(currPath,'config.ini'),'tesesection', 'name', 'hello word')

doexcel.py

 1 '''
 2 Code description: read excel.xlsx, get values
 3 Create time: 
 4 Developer: 
 5 '''
 6 
 7 import xlrd
 8 import os
 9 import logging
10 from retail.config import conf
11 from retail.test_case.models.log import Logger
12 
13 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)
14 
15 class ReadExcel(object):
16 
17     def __init__(self,fileName='elementDate.xlsx',sheetName='elementsInfo'):
18         """
19 
20         :param fileName:
21         :param sheetName:
22         """
23         try:
24             self.dataFile = os.path.join(conf.dataPath, fileName)
25             self.workBook = xlrd.open_workbook(self.dataFile)
26             self.sheetName = self.workBook.sheet_by_name(sheetName)
27         except Exception:
28             log.logger.exception('init class ReadExcel fail', exc_info=True)
29             raise
30         else:
31             log.logger.info('initing class ReadExcel')
32     # Reading data in excel
33     def readExcel(self,rownum,colnum):
34         """
35 
36         :param rownum:
37         :param colnum:
38         :return:
39         """
40         try:
41             value = self.sheetName.cell(rownum,colnum).value
42         except Exception:
43             log.logger.exception('read value from excel file fail', exc_info=True)
44             raise
45         else:
46             log.logger.info('reading value [%s] from excel file [%s] completed' %(value, self.dataFile))
47             return value
48 
49 if __name__ == '__main__':
50     cellValue = ReadExcel().readExcel(1,3)
51     print((cellValue))

log.py

 1 '''
 2 Code description: log info
 3 Create time: 
 4 Developer: 
 5 '''
 6 
 7 import logging
 8 import time
 9 
10 
11 class Logger(object):
12     def __init__(self, logger, CmdLevel=logging.INFO, FileLevel=logging.INFO):
13         """
14 
15         :param logger:
16         :param CmdLevel:
17         :param FileLevel:
18         """
19         self.logger = logging.getLogger(logger)
20         self.logger.setLevel(logging.DEBUG)  # Sets the default level of log output
21         # Log output format
22         fmt = logging.Formatter('%(asctime)s - %(filename)s:[%(lineno)s] - [%(levelname)s] - %(message)s')
23         # Log file name
24         # self.LogFileName = os.path.join(conf.log_path, "{0}.log".format(time.strftime("%Y-%m-%d")))# %H_%M_%S
25         currTime = time.strftime("%Y-%m-%d")
26         self.LogFileName = r'D:\Petrochina_Retail_Test_Project\retail\report\Log\log'+currTime+'.log'
27         # Set console output
28         # sh = logging.StreamHandler()
29         # sh.setFormatter(fmt)
30         # sh.setLevel(CmdLevel)# log level
31 
32         # Set file output
33         fh = logging.FileHandler(self.LogFileName)
34         fh.setFormatter(fmt)
35         fh.setLevel(FileLevel)# log level
36 
37         # self.logger.addHandler(sh)
38         self.logger.addHandler(fh)
39 
40     # def debug(self, message):
41     #     """
42     #
43     #     :param message:
44     #     :return:
45     #     """
46     #     self.logger.debug(message)
47     #
48     # def info(self,message):
49     #     """
50     #
51     #     :param message:
52     #     :return:
53     #     """
54     #     self.logger.info(message)
55     #
56     # def warn(self,message):
57     #     """
58     #
59     #     :param message:
60     #     :return:
61     #     """
62     #     self.logger.warning(message)
63     #
64     # def error(self,message):
65     #     """
66     #
67     #     :param message:
68     #     :return:
69     #     """
70     #     self.logger.error(message)
71     #
72     # def criti(self,message):
73     #     """
74     #
75     #     :param message:
76     #     :return:
77     #     """
78     #     self.logger.critical(message)
79 
80 if __name__ == '__main__':
81     logger = Logger("fox",CmdLevel=logging.DEBUG, FileLevel=logging.DEBUG)
82     logger.logger.debug("debug")
83     logger.logger.log(logging.ERROR,'%(module)s %(info)s',{'module':'log journal','info':'error'}) #ERROR,log error

sendmail.py

  1 '''
  2 Code description: send email
  3 Create time: 
  4 Developer: 
  5 '''
  6 
  7 import smtplib
  8 from email.mime.text import MIMEText
  9 from email.header import Header
 10 import os
 11 from retail.config import conf
 12 from retail.test_case.models.log import Logger
 13 
 14 log = Logger(__name__)
 15 #   Mail sending interface
 16 class SendMail(object):
 17     '''
 18     Mail configuration information
 19     '''
 20     def __init__(self,
 21                  receiver,
 22                  subject='Retail System test report',
 23                  server='smtp.qq.com',
 24                  fromuser='281754043@qq.com',
 25                  frompassword='gifhhsbgqyovbhhc',
 26                  sender='281754043@qq.com'):
 27         """
 28 
 29         :param receiver:
 30         :param subject:
 31         :param server:
 32         :param fromuser:
 33         :param frompassword:
 34         :param sender:
 35         """
 36 
 37         self._server = server
 38         self._fromuser = fromuser
 39         self._frompassword = frompassword
 40         self._sender = sender
 41         self._receiver = receiver
 42         self._subject = subject
 43 
 44     def sendEmail(self, fileName):
 45         """
 46 
 47         :param filename:
 48         :return:
 49         """
 50         #   Open the report file and read the contents of the file
 51         try:
 52             f = open(os.path.join(conf.reportPath, fileName), 'rb')
 53             fileMsg = f.read()
 54         except Exception:
 55             log.logger.exception('open or read file [%s] failed,No such file or directory: %s' %(fileName, conf.reportPath))
 56             log.logger.info('open and read file [%s] successed!' %fileName)
 57         else:
 58             f.close()
 59             #   Mail subject
 60             subject = 'Python test report' #
 61             #   Mail Settings
 62             msg = MIMEText(fileMsg, 'html', 'utf-8')
 63             msg['subject'] = Header(subject, 'utf-8')
 64             msg['from'] = self._sender
 65         #   Connect to the server, log in to the server and send mail
 66             try:
 67                 smtp = smtplib.SMTP()
 68                 smtp.connect(self._server)
 69                 smtp.login(self._fromuser, self._frompassword)
 70             except Exception:
 71                 log.logger.exception('connect [%s] server failed or username and password incorrect!' %smtp)
 72             else:
 73                 log.logger.info('email server [%s] login success!' %smtp)
 74                 try:
 75                     smtp.sendmail(self._sender, self._receiver, msg.as_string())
 76                 except Exception:
 77                     log.logger.exception('send email failed!')
 78                 else:
 79                     log.logger.info('send email successed!')
 80 
 81 
 82 #   Read mail recipient information from file
 83 def getReceiverInfo(fileName):
 84     '''
 85     :param filename: Read recipient information
 86     :return: Recipient information
 87     '''
 88     try:
 89         openFile = open(os.path.join(conf.dataPath, fileName))
 90     except Exception:
 91         log.logger.exception('open or read file [%s] failed,No such file or directory: %s' %(fileName, conf.dataPath))
 92     else:
 93         log.logger.info('open file [%s] successed!' %fileName)
 94         for line in openFile:
 95             msg = [i.strip() for i in line.split(',')]
 96             log.logger.info('reading [%s] and got receiver value is [%s]' %(fileName, msg))
 97             return msg
 98 
 99 if __name__ == '__main__':
100     readMsg=getReceiverInfo('mail_receiver.txt')
101     sendmail = SendMail(readMsg)
102     sendmail.sendEmail('2018-09-21 17_44_04.html')

strhandle.py

1 '''
 2 Code description:  string handle
 3 Create time: 
 4 Developer: 
 5 '''
 6 
 7 import logging
 8 from retail.test_case.models.log import Logger
 9 
10 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)
11 def strhandle(str):
12     """
13 
14     :param str:
15     :return:
16     """
17     #Initializes the counting of characters, numbers, spaces, and special characters
18     try:
19         lowerCase = 0
20         upperCase = 0
21         number = 0
22         other = 0
23         for stritem in str:
24          #If there are lowercase letters in the string, the number of lowercase letters + 1
25             if stritem.islower():
26                 lowerCase += 1
27             #If there are numbers in the string, the number of numbers + 1
28             elif stritem.isdigit():
29                 number += 1
30             elif stritem.isupper():# capital
31                 upperCase +=1
32             #If there are spaces in the string, the number of spaces is + 1
33             else:
34                 other += 1
35         return lowerCase, upperCase, number, other
36     except Exception as e:
37         log.logger.exception('string handle error , please check!', exc_info=True)
38         raise e
39 
40 
41 if __name__=='__main__':
42     list = ['qwert','erwer']
43     lowercase, uppercase, number, other = strhandle(list[0])
44     print ("The lowercase letters in this string are:%d" %lowercase)
45     print ("The big letters in the string are:%d" %uppercase)
46     print ("The numbers in this string are:%d" %number)
47     print ("The special characters in this string are:%d" %other)

testreport.py

 1 '''
 2 Code description: test report
 3 Create time: 
 4 Developer: 
 5 '''
 6 
 7 
 8 import time
 9 import logging
10 import unittest
11 from BeautifulReport import BeautifulReport
12 import HTMLTestRunner
13 from retail.config import conf
14 from retail.test_case.models.log import Logger
15 
16 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)
17 # Test report implemented with HTMLTestRunner
18 def testreport():
19     """
20 
21     :return:
22     """
23     currTime = time.strftime('%Y-%m-%d %H_%M_%S')
24     fileName = conf.reportPath + r'\report' + currTime + '.html'
25     try:
26         fp = open(fileName, 'wb')
27     except Exception :
28         log.logger.exception('[%s] open error cause Failed to generate test report' %fileName)
29     else:
30         runner = HTMLTestRunner.HTMLTestRunner\
31             (stream=fp, title='Retail sys Test report',
32                                                description='processor:Intel(R) Core(TM) '
33                                                            'i5-6200U CPU @ 2030GHz 2.40 GHz '
34                                                 'Memory:8G System type: 64 Bit version: windows 10 Family Chinese version')
35         log.logger.info('successed to generate test report [%s]' %fileName)
36         return runner, fp, fileName
37 #
38 def addTc(TCpath = conf.tcPath, rule = '*TC.py'):
39     """
40 
41     :param TCpath: Test case storage path
42     :param rule: Matched test case file
43     :return:  test suite
44     """
45     discover = unittest.defaultTestLoader.discover(TCpath, rule)
46 
47     return discover
48 # Implementation of test report with BeautifulReport module
49 def runTc(discover):
50     """
51 
52     :param discover: test suite
53     :return:
54     """
55     currTime = time.strftime('%Y-%m-%d %H_%M_%S')
56     fileName = currTime+'.html'
57     try:
58         result = BeautifulReport(discover)
59         result.report(filename=fileName, description='Test report', log_path=conf.reportPath)
60     except Exception:
61         log.logger.exception('Failed to generate test report', exc_info=True)
62     else:
63         log.logger.info('successed to generate test report [%s]' % fileName)
64         return fileName
65 
66 if __name__ == '__main__':
67     testreport()
68     suite = addTc(rule = '*TC.py')
69     runTc(suite)

driver.py

 1 '''
 2 Code description: save all driver info
 3 Create time: 
 4 Developer: 
 5 '''
 6 
 7 from selenium import webdriver
 8 import logging
 9 import sys
10 from retail.test_case.models.log import Logger
11 
12 
13 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)
14 class WDriver(object):
15 
16     # Firefox driver
17     def fireFoxDriver(self):
18         """
19 
20         :return:
21         """
22         try:
23             self.driver = webdriver.Firefox()
24         except Exception as e:
25             log.logger.exception('FireFoxDriverServer.exe executable needs to be in PATH. Please download!', exc_info=True)
26             raise e
27         else:
28             log.logger.info('%s:found the Firefox driver [%s] successed !' %(sys._getframe().f_code.co_name,self.driver))
29             return self.driver
30 
31     # chrom driver
32     def chromeDriver(self):
33         """
34 
35         :return:
36         """
37         try:
38             # option = webdriver.ChromeOptions()# The implementation does not open the browser to execute the web automation test script
39             # option.add_argument('headless')#
40             # self.driver = webdriver.Chrome(chrome_options=option)
41             self.driver = webdriver.Chrome()
42         except Exception as e:
43             log.logger.exception('ChromeDriverServer.exe executable needs to be in PATH. Please download!',
44                                  exc_info=True)
45             raise e
46         else:
47             log.logger.info('%s:found the chrome driver [%s] successed !' % (sys._getframe().f_code.co_name, self.driver))
48             return self.driver
49 
50 
51     # Ie driver
52     def ieDriver(self):
53         """
54 
55         :return:
56         """
57         try:
58             self.driver = webdriver.Ie()
59         except Exception as e:
60             log.logger.exception('IEDriverServer.exe executable needs to be in PATH. Please download!',
61                                  exc_info=True)
62             raise e
63         else:
64             log.logger.info('%s:found the IE driver [%s] successed !' % (sys._getframe().f_code.co_name, self.driver))
65             return self.driver
66 
67 
68 if __name__ == '__main__':
69     WDrive=WDriver()
70     WDrive.fireFoxDriver()

myunittest.py

 1 '''
 2 Code description: unittest framwork
 3 Create time: 
 4 Developer: 
 5 '''
 6 
 7 from retail.test_case.models.driver import WDriver
 8 import logging
 9 import unittest
10 from retail.test_case.page_obj.login_page import LoginPage
11 from retail.test_case.models.log import Logger
12 from selenium import webdriver
13 
14 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)
15 class MyunitTest(unittest.TestCase):
16     """
17 
18     """
19 
20     # add by xuechao at 2018.09.19
21     @classmethod
22     def setUpClass(cls): # A test class (file) executes to open the browser once, saving the time of opening the browser once for each use case
23 
24         #cls.driver = WDriver().fireFoxDriver()
25         cls.driver = WDriver().chromeDriver()
26         cls.driver.maximize_window()
27         log.logger.info('opened the browser successed!')
28     # ----------------------------
29 
30     def setUp(self):
31         """
32 
33         :return:
34         """
35         self.login = LoginPage(self.driver)
36         self.login.open()
37         log.logger.info('************************starting run test cases************************')
38 
39     def tearDown(self):
40         """
41 
42         :return:
43         """
44         self.driver.refresh()
45         log.logger.info('************************test case run completed************************')
46 
47     # add by linuxchao at 2018.09.19
48     @classmethod
49     def tearDownClass(cls):
50         cls.driver.quit()
51         log.logger.info('quit the browser success!')
52     #----------------------------
53 if __name__ == '__main__':
54     unittest.main()

So far, all the public methods I need have been compiled, and other methods can be added later. Let's start writing our test cases. Since we use the PageObject mode, we need to design a basepage page page. All pages or modules inherit this basepage. basepage mainly writes the public methods of all pages

 base_page.py

Login page

 login_page.py

Login test case

 LoginTc.py

Modify password page

 modifypw_page.py

Modify password test case

 ModifyPw.py

Member profile query page

 memberquery_page.py

Member file query case

 MemberQueryTc.py

Execute test cases

 RunTc.py

From beautiful report import beautiful report this report needs to be found online (many similar test report source codes do not necessarily use the report template in this case)

Report display

There is no report until you pay. Next, let's take a look at our achievements

1. Screenshot:

Screenshot of rule creation failure


Screenshot of successful login

Case execution log:

 journal

Test report:

summary

Seeing the results, I still have a sense of accomplishment. I didn't send the screenshot of the email, because I'm on the intranet. I don't know why the email server can't connect, but there's no problem using the Internet to test the email sending alone!

Just write so much. The use case design ideas of other pages are the same, because all use cases are independent of each other, so more and less will not affect each other!

Software testing is the easiest subject to get started in IT related industries ~ IT does not need the logical thinking of developers and the 24-hour standby of operation and maintenance personnel. What is needed is a careful attitude and a wide understanding of IT related knowledge points. The growth path of each tester from entering the industry to becoming a professional bull can be divided into three stages: software testing, automated testing and test development engineer.

If you don't want to experience the feeling that you can't find materials and no one answers questions during self-study, and give up after a few days, you can add our software testing exchange group 313782132, which contains various software testing materials and technical exchanges.

Tags: Python unit testing software testing Testing Stress testing

Posted by ywickham on Mon, 09 May 2022 22:57:05 +0300