Étapes et résumé de la création d'un cadre de test automatisé basé sur les données à partir de zéro à l'aide de Python Webdriver

Processus étape par étape et résumé de la création d'un cadre de test basé sur les données

Après avoir appris de M. Wu à créer un cadre automatisé basé sur les données, lorsque je pratiquais seul, j'ai essayé d'étendre et d'optimiser le programme simple petit à petit pour mettre en œuvre ce cadre basé sur les données.

Parlons d’abord de l’objectif de la création d’un cadre de tests automatisés :

La première consiste à réaliser le fonctionnement automatisé d'une fonction sans avoir à effectuer manuellement un travail répétitif à chaque fois.Utiliser des programmes automatisés pour remplacer le travail manuel et améliorer l'efficacité, comme l'exécution répétée de tests de régression.

La seconde consiste à encapsuler les données et les opérations sur les données, à réduire l'écriture de codes répétés et à séparer les données de test et les programmes, afin que les testeurs automatisés n'aient pas besoin de prêter trop d'attention au code.

En conservant correctement les données, vous pouvez effectuer une exécution automatisée efficace des tests, une bonne réutilisabilité et de nombreux autres avantages. . .

Permettez-moi de parler du résumé du processus après avoir construit ce framework à partir de zéro :

Implémentez d'abord la fonction à implémenter dans un fichier, puis encapsulez une certaine fonction dispersée, appelez la méthode encapsulée dans le programme principal et divisez l'ensemble du processus en plusieurs étapes.Chaque étape n'implémente qu'une seule encapsulation ou optimisation.

Tout comme pour disposer des blocs de construction, après avoir terminé un endroit, placez-vous à ce nœud et réfléchissez à ce que je peux encapsuler et optimiser ensuite, puis faites un pas en avant, puis réfléchissez à ce qui peut être optimisé sur cette base.

Jusqu'à ce que le framework de test soit construit, le processus est d'abord séparé de la structure du framework. Au lieu de penser à ce à quoi ressemblera le framework, nous pensons simplement à ce que l'encapsulation et l'optimisation peuvent être faites avec le programme existant, et comment changer pour le rendre plus utilisable.

Cela semble plus organisé, puis lorsque je réfléchis aux parties qui peuvent être extraites pour créer des packages séparés, je comparerai certaines structures de framework et sous quels types de packages ce type de package peut être placé. J'optimiserai le package et le classerai dans le même temps.

Lorsque nous encapsulons le programme et le mettons dans le fichier de configuration, nous le mettons dans le fichier de configuration. En fin de compte, vous constaterez que ce que vous obtenez de ce processus est un cadre de test.

Une fois ce processus terminé, il sera beaucoup plus facile de comprendre la fonction de chaque module à partir de l'architecture globale du framework de test, car lorsque vous l'optimiserez et l'encapsulerez à partir de zéro, vous obtiendrez enfin ces modules.

Ensuite, lorsque vous apprenez les frameworks de test pour différents types de pilotes, les principes sont fondamentalement les mêmes.

Voici le processus global de construction de ce cadre :
Tout d'abord, il est clair que ce que je veux réaliser est la fonction de connexion à la boîte aux lettres 126 et d'ajout de contacts.


Étape 1 : Si je n'utilise pas le framework et que je liste le code directement, comment puis-je y parvenir ? Essayons d'abord de terminer cela. Créez
un nouveau projet dans pycharm -dataDrivenTestPractice1.
Créez un nouveau package TestScript sous le projet.
Créer un package TestScript sous le package TestScript.

code de fichier python :
#encoding=utf-8
#author-Xia Xiaoxu
de selenium import webdriver
import time
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException, NoSuchElementException
import traceback

driver=webdriver.Firefox(executable_path='c:\\geckodriver')
driver.get('http://mail.126.com')
essayez :
    wait=WebDriverWait(driver ,10,0.2)#Afficher en attente
    driver.switch_to.frame(driver.find_element_by_xpath("//iframe[@id='x-URS-iframe']"))#Basculez vers l'élément frame où se trouve la zone de saisie du nom d'utilisateur et du mot de passe name=wait.until (lambda x
    : x.find_element_by_xpath("//input[@placeholder='Compte de messagerie ou numéro de téléphone portable' et @name='email']")) name.send_keys('xiaxiaoxu1987') password=wait.until
    (
    lambda x:x.find_element_by_xpath ("//input[@placeholder='password']"))
    password.send_keys('gloryroad')
    submit=wait.until(lambda x:x.find_element_by_xpath("//a[@id= 'dologin']" ))
    submit.click()
    driver.switch_to.default_content()#L'utilisation de switch_to_default_content() dans pycharm sera barrée, et
    time.sleep(5)
    affirme que vous "exit" dans driver.page_source,"il n'existe pas dans page_source"
    address_book_link=wait.until(lambda x:x.find_element_by_xpath("//div[text()='通讯录']"))
    address_book_link.click()
    #assert u"新建联系人" dans driver.page_source
    add_contact_button=wait .until(lambda x:x.find_element_by_xpath("//span[text()='新建联系人']"))
    add_contact_button.click()
    contact_name=wait.until(lambda x:x.find_element_by_xpath("//a [@title='编辑详细姓名']/preceding-sibling::div/input"))
    contact_name.send_keys(u"徐凤钗")
    contact_email=wait.until(lambda x:x.find_element_by_xpath("//*[@ id='iaddress_MAIL_wrap']//input"))
    contact_email.send_keys("[email protected]")
    contact_is_star=wait.until(lambda x:x.find_element_by_xpath("//span[text()='Définir comme contact étoile']/preceding-sibling::span/b"))
    contact_is_star.click()
    contact_mobile=wait.until(lambda x:x.find_element_by_xpath("//*[@id='iaddress_TEL_wrap']//dd//input")) contact_mobile.send_keys
    ('18141134488')
    contact_other_info=wait .until(lambda x:x.find_element_by_xpath("//textarea"))
    contact_other_info.send_keys('ma femme')
    contact_save_button=wait.until(lambda x:x.find_element_by_xpath("//span[.='确 定' ]"))
    contact_save_button.click()

except TimeoutException, e:
    # 捕获TimeoutException et
    print traceback.print_exc()

except NoSuchElementException, e:
    # 捕获NoSuchElementException异常
    print traceback.print_exc()

except Exception, e:
    #Attrapez d'autres exceptions
    print résultat traceback.print_exc()

 : la connexion et l'ajout de contacts sont corrects
C:\Python27\python.exe D:/test/dataDrivenTestPractice1/TestScript.py

Processus terminé avec le code de sortie 0

À ce stade, la première étape a été mise en œuvre. Voyons ensuite comment séparer le programme et les données dans ce programme.
Jetons un coup d'œil aux principales fonctions du programme :

Connectez-vous à votre messagerie-->Ouvrez la page de contact-->Cliquez sur le bouton Ajouter un contact-->Entrez les informations de contact dans la fenêtre contextuelle-->Cliquez sur le bouton Enregistrer.

Il y a aussi le noyau du data-driven -> séparation des données et des programmes

Tout d'abord, les étapes de connexion à la boîte aux lettres peuvent être extraites et empaquetées indépendamment.Le module de connexion est provisoirement désigné.

Ensuite, nous allons encapsuler la fonction de connexion et l'appeler dans le programme.

Étape 2 : extrayez la fonction de connexion, encapsulez-la et appelez-la dans le programme principal
Créer un nouveau package PageObject sous le projet
Créez un nouveau fichier python de LoginPage sous le package PageObject pour encapsuler l'opération de connexion.
Code:

#encodage=utf-8

#auteur-Xia Xiaoxu

à partir du pilote Web d'importation de sélénium

heure d'importation

à partir de selenium.webdriver.support.ui importer WebDriverWait

à partir de selenium.webdriver.common.by import Par

à partir de selenium.common.exceptions importer TimeoutException, NoSuchElementException

traçage des importations

classe LoginPage (objet):

    def __init__ (soi, pilote) :

        self.driver=pilote

    connexion par défaut (auto):

        essayer:

            wait = WebDriverWait(driver, 10, 0.2) # Affichage en attente

            self.driver.switch_to.frame(self.driver.find_element_by_xpath("//iframe[@id='x-URS-iframe']")) # Basculer vers l'élément frame où se trouvent les zones de saisie du nom d'utilisateur et du mot de passe

            name = wait.until(lambda x: x.find_element_by_xpath("//input[@placeholder='Compte de messagerie ou numéro de téléphone mobile' et @name='email']"))

            nom.send_keys('xiaxiaoxu1987')

            mot de passe = wait.until(lambda x: x.find_element_by_xpath("//input[@placeholder='密码']"))

            mot de passe.send_keys('gloryroad')

            submit = wait.until(lambda x: x.find_element_by_xpath("//a[@id='dologin']"))

            soumettre.click()

            self.driver.switch_to.default_content() # Si vous utilisez switch_to_default_content() dans pycharm, il sera barré et supprimé.

            temps.sommeil(5)

            affirmez-vous "退出" dans self.driver.page_source, "n'existe pas dans page_source"

        sauf TimeoutException, e :

            #Catch TimeoutExceptionexception

            imprimer traceback.print_exc()

        sauf NoSuchElementException, e :

            #Catch NoSuchElementExceptionexception

            imprimer traceback.print_exc()

        sauf exception, e :

            #Attrapez d'autres exceptions

            imprimer traceback.print_exc()

si __name__=="__main__":

    driver=webdriver.Firefox(executable_path='c:\\geckodriver')

    driver.get("http:\\mail.126.com")

    login = Page de connexion (pilote)

    Connexion Connexion()

Résultat : connexion réussie

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/PageObject/Login_page.py

Processus terminé avec le code de sortie 0

À ce stade, la fonction de connexion est encapsulée. Ensuite, modifiez le programme principal et appelez LoginPage.
TestScript.py :

#encodage=utf-8

#auteur-Xia Xiaoxu

à partir du pilote Web d'importation de sélénium

heure d'importation

à partir de selenium.webdriver.support.ui importer WebDriverWait

à partir de selenium.webdriver.common.by import Par

à partir de selenium.common.exceptions importer TimeoutException, NoSuchElementException

traçage des importations

à partir de l'importation PageObject.Login_Page *

driver=webdriver.Firefox(executable_path='c:\\geckodriver')

driver.get('http://mail.126.com')

lp = Page de connexion (pilote)

wait = WebDriverWait(driver, 10, 0.2) # Affichage en attente

essayer:

    lp.login()

    address_book_link=wait.until(lambda x:x.find_element_by_xpath("//div[text()='通讯录']"))

    adresse_book_link.click()

    #affirmez que vous êtes "Nouveau contact" dans driver.page_source

    add_contact_button=wait.until(lambda x:x.find_element_by_xpath("//span[text()='New Contact']"))

    add_contact_button.click()

    contact_name=wait.until(lambda x:x.find_element_by_xpath("//a[@title='Modifier le nom détaillé']/preceding-sibling::div/input"))

    contact_name.send_keys(u"徐凤钗")

    contact_email=wait.until(lambda x:x.find_element_by_xpath("//*[@id='iaddress_MAIL_wrap']//input"))

    contact_email.send_keys("[email protected]")

    contact_is_star=wait.until(lambda x:x.find_element_by_xpath("//span[text()='Définir comme contact étoile']/preceding-sibling::span/b"))

    contact_is_star.click()

    contact_mobile=wait.until(lambda x:x.find_element_by_xpath("//*[@id='iaddress_TEL_wrap']//dd//input"))

    contact_mobile.send_keys('18141134488')

    contact_other_info=wait.until(lambda x:x.find_element_by_xpath("//textarea"))

    contact_other_info.send_keys('ma femme')

    contact_save_button=wait.until(lambda x:x.find_element_by_xpath("//span[.='确 定']"))

    contact_save_button.click()

sauf TimeoutException, e :

    #Catch TimeoutExceptionexception

    imprimer traceback.print_exc()

sauf NoSuchElementException, e :

    #Catch NoSuchElementExceptionexception

    imprimer traceback.print_exc()

sauf exception, e :

    #Attrapez d'autres exceptions

    imprimer traceback.print_exc()

Résultat : Succès

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/TestScript/TestScript.py

Processus terminé avec le code de sortie 0

Du point de vue du programme principal, l'action d'ajouter des contacts peut également être encapsulée. Encapsulons d'abord cette partie. S'il y a des problèmes plus tard, nous pouvons revenir en arrière et le déduire. Faites-le d'abord selon cette idée, puis faites encore une fois.

Étape 3 : Encapsuler la fonction d'ajout de contacts
Créez un nouveau fichier python AddressBook sous le package PageObject
CodeAddressBook.py :

#encodage=utf-8

#auteur-Xia Xiaoxu

à partir du pilote Web d'importation de sélénium

heure d'importation

à partir de selenium.webdriver.support.ui importer WebDriverWait

à partir de selenium.webdriver.common.by import Par

à partir de selenium.common.exceptions importer TimeoutException, NoSuchElementException

traçage des importations

à partir de l'importation PageObject.Login_Page *

classe Carnet d'adresses (objet):

    def __init__ (soi, pilote) :

        self.driver=pilote

    def add_contact(soi) :

        essayer:

            wait = WebDriverWait(self.driver, 10, 0.2) # Affichage en attente

            address_book_link = wait.until(lambda x: x.find_element_by_xpath("//div[text()='通讯录']"))

            adresse_book_link.click()

            # affirmez votre "Nouveau contact" dans driver.page_source

            add_contact_button = wait.until(lambda x: x.find_element_by_xpath("//span[text()='New Contact']"))

            add_contact_button.click()

            nom_contact = attendre.jusqu'à(

                lambda x : x.find_element_by_xpath("//a[@title='Modifier le nom détaillé']/preceding-sibling::div/input"))

            contact_name.send_keys(u"徐凤钗")

            contact_email = wait.until(lambda x: x.find_element_by_xpath("//*[@id='iaddress_MAIL_wrap']//input"))

            contact_email.send_keys("[email protected]")

            contact_is_star = attendre.jusqu'à(

                lambda x : x.find_element_by_xpath("//span[text()='Set as star contact']/preceding-sibling::span/b"))

            contact_is_star.click()

            contact_mobile = wait.until(lambda x: x.find_element_by_xpath("//*[@id='iaddress_TEL_wrap']//dd//input"))

            contact_mobile.send_keys('18141134488')

            contact_other_info = wait.until(lambda x: x.find_element_by_xpath("//textarea"))

            contact_other_info.send_keys('ma femme')

            contact_save_button = wait.until(lambda x: x.find_element_by_xpath("//span[.='确 定']"))

            contact_save_button.click()

        sauf TimeoutException, e :

            #Catch TimeoutExceptionexception

            imprimer traceback.print_exc()

        sauf NoSuchElementException, e :

            #Catch NoSuchElementExceptionexception

            imprimer traceback.print_exc()

        sauf exception, e :

            #Attrapez d'autres exceptions

            imprimer traceback.print_exc()

si __name__=="__main__":

    driver=webdriver.Firefox(executable_path='c:\\geckodriver')

    driver.get('http://mail.126.com')

    lp = Page de connexion (pilote)

    lp.login()

    ab=Carnet d'adresses (pilote)

    ab.add_contact()

Résultat : Succès

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/PageObject/AddressBook.py

Processus terminé avec le code de sortie 0

À ce stade, la fonction d'ajout de contacts est à peu près encapsulée. Appelez-la maintenant dans le programme principal.
TestScript.py :

#encodage=utf-8

#auteur-Xia Xiaoxu

à partir du pilote Web d'importation de sélénium

heure d'importation

à partir de selenium.webdriver.support.ui importer WebDriverWait

à partir de selenium.webdriver.common.by import Par

à partir de selenium.common.exceptions importer TimeoutException, NoSuchElementException

traçage des importations

à partir de l'importation PageObject.Login_Page *

à partir de l'importation PageObject.AddressBook *

driver=webdriver.Firefox(executable_path='c:\\geckodriver')

driver.get('http://mail.126.com')

loginPage = Page de connexion (pilote)

adresseBook = Carnet d'adresses (pilote)

connexionPage.login()

carnet d'adresses.add_contact()

Résultat : Succès

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/TestScript/TestScript.py

Processus terminé avec le code de sortie 0

À ce stade, les deux fonctions du programme - se connecter et ajouter des contacts - ont été grossièrement encapsulées. Vous pouvez appeler la fonction directement dans le programme principal. Passons en revue les principales fonctions du programme :

Connectez-vous à votre messagerie-->Ouvrez la page de contact-->Cliquez sur le bouton Ajouter un contact-->Entrez les informations de contact dans la fenêtre contextuelle-->Cliquez sur le bouton Enregistrer. Il y a aussi le noyau du data-driven -> séparation des données et des programmes

Ensuite, je veux essayer d’extraire une partie des données. Voyons comment séparer ces données ?

Du point de vue du programme, la partie qui appelle les données se trouve dans les deux modules qui viennent d'être encapsulés, Login_Page et AddressBook. Voyons comment le programme utilise les données.

Page de connexion:

Carnet d'adresses:

Lors de l'encapsulation de ces deux fonctions, aucun paramètre n'est laissé de côté, et ils sont écrits directement dans la fonction. C'est évidemment relativement faible, alors comment faire ? Essayons de remplacer les données qui doivent être appelées dans la fonction par des paramètres, puis transmettons les paramètres lors de l'appel.

Modifions d'abord la fonction de connexion et voyons comment la modifier pour utiliser les paramètres. À ce moment-là, je suis soudainement devenu confus. Avec autant de données différentes, il n'y a aucun moyen d'utiliser des paramètres. . .

Si vous souhaitez utiliser le transfert de paramètres, vous devez diviser la fonction de connexion. Vous pouvez voir qu'il existe plusieurs parties de la fonction de connexion qui peuvent être encapsulées. Par exemple, recherchez la fonction de l'élément frame, recherchez la fonction du nom d'utilisateur élément de la zone de saisie, puis recherchez le seul Dans la fonction de l'élément, vous pouvez transmettre des données aux paramètres de recherche.

Étape 4 : Encapsuler la fonction de recherche d'éléments
Modifier LoginPage.py :

#encodage=utf-8

#auteur-Xia Xiaoxu

à partir du pilote Web d'importation de sélénium

heure d'importation

à partir de selenium.webdriver.support.ui importer WebDriverWait

à partir de selenium.webdriver.common.by import Par

à partir de selenium.common.exceptions importer TimeoutException, NoSuchElementException

traçage des importations

classe LoginPage (objet):

    def __init__ (soi, pilote) :

        self.driver=pilote

        self.wait = WebDriverWait(self.driver, 10, 0.2) # Afficher l'attente

    def getFrame(self,locateType,locateExpression) :

        frame=self.wait.until(lambda x: x.find_element(by=locateType,value=locateExpression))#"//iframe[@id='x-URS-iframe']"

        trame de retour

    def getUserName(self,locateType,locateExpression) :

        userName=self.wait.until(lambda x: x.find_element(by=locateType,value=locateExpression))#"//input[@placeholder='Compte de messagerie ou numéro de téléphone mobile' et @name='email']"

        renvoyer le nom d'utilisateur

    def getPassword(self,locateType,locateExpression) :

        password=self.wait.until(lambda x: x.find_element(by=locateType,value=locateExpression))#"//input[@placeholder='密码']"

        retourner le mot de passe

    def getLoginButton(self,locateType,locateExpression) :

        loginButton=self.wait.until(lambda x: x.find_element(by=locateType,value=locateExpression))#"//a[@id='dologin']"

        retourner le bouton de connexion

si __name__=="__main__":

    driver=webdriver.Firefox(executable_path='c:\\geckodriver')

    driver.get("http:\\mail.126.com")

    lp = Page de connexion (pilote)

    driver.switch_to.frame(lp.getFrame("xpath","//iframe[@id='x-URS-iframe']"))

    temps.sommeil(2)

    lp.getUserName("xpath","//input[@placeholder='compte de messagerie ou numéro de téléphone mobile' et @name='email']").clear()

    lp.getUserName("xpath","//input[@placeholder='compte de messagerie ou numéro de téléphone portable' et @name='email']").send_keys("xiaxiaoxu1987")

    lp.getPassword("xpath","//input[@placeholder='密码']").send_keys("gloryroad")

    lp.getLoginButton("xpath","//a[@id='dologin']").click()

    driver.switch_to.default_content()

    temps.sommeil(5)

    affirmez que vous "退出" dans driver.page_source, "n'existe pas dans page_source"

Résultat : connexion réussie
À ce stade, bien que les données soient transmises en paramètre à chaque fonction qui recherche des éléments, il existe un problème.

Lors d'un appel, vous devez saisir manuellement les données nécessaires pour trouver l'élément, ce qui est plus gênant. Si vous saisissez une mauvaise lettre, l'élément ne sera pas trouvé. Comment faire ?

Il doit être réencapsulé, mettre les données dans un fichier, puis encapsuler la méthode pour lire les données du fichier. De cette façon, vous devez créer un fichier de configuration pour stocker les données, puis créer un nouveau python fichier pour encapsuler la méthode de lecture du fichier de configuration.

Étape 5 : placez les données dans le fichier de configuration, puis encapsulez la méthode pour lire les données du fichier
Créez un nouveau package appelé Conf sous le projet (utilisé pour stocker les fichiers liés à la configuration) :
Créez un nouveau fichier sous le package Conf : PageObjectRepository.ini

PageObjectRepository.ini

[126mail_login]

login_page.frame=id>x-URS-iframe

login_page.username=xpath>//input[@name='email']

login_page.password=xpath>//input[@name='password']

login_page.loginbutton=id>dologin

[126mail_homepage]

home_page.addressbook=xpath>//div[text()='Carnet d'adresses']

[126mail_addcontactspage]

addcontacts_page.createcontactsbtn=xpath>//span[text()='Nouveau contact']

addcontacts_page.contactpersonname=xpath>//a[@title='Modifier le nom détaillé']/preceding-sibling::div/input

addcontacts_page.contactpersonemail=xpath>//*[@id='iaddress_MAIL_wrap']//input

addcontacts_page.starcontacts=xpath>//span[text()='Définir comme contact étoile']/preceding-sibling::span/b

addcontacts_page.contactpersonmobile=xpath>//*[@id='iaddress_TEL_wrap']//dd//input

addcontacts_page.contactpersoncomment=xpath>//textarea

addcontacts_page.savecontaceperson=xpath>//span[.='OK']

Créez un nouveau package Util sous le projet. Ce package est généralement utilisé pour stocker des classes d'outils, telles que la lecture de fichiers de configuration, la recherche de méthodes d'éléments, les classes d'opérations Excel, les classes de temps, les méthodes et opérations de journalisation, les captures d'écran, les modèles de rapport, etc.
Créez un nouveau fichier python sous le package Util : ParsePageObjectRepository.py pour encapsuler la classe de lecture des fichiers de configuration.

#encodage=utf-8

#auteur-Xia Xiaoxu

à partir de ConfigParser importer ConfigParser

classe ParsePageObjectRepositoryConfig (objet) :

    def __init__(self,config_path) :

        self.cf=ConfigParser()#Générer l'analyseur

        self.cf.read(config_path)

    def getItemSection(self,sectionName) :

        imprimer self.cf.items(sectionName)

        retourner dict(self.cf.items(sectionName))

    def getOptionValue(self,sectionName,optionName):#Renvoyer un dictionnaire

        print self.cf.get(sectionName,optionName)

        return self.cf.get(sectionName,optionName)

si __name__=='__main__' :

    pp=ParsePageObjectRepositoryConfig( "D:\\test\\dataDrivenTestPractice1\\Conf\\PageObjectRepository.ini" )

    imprimer pp.getItemSection("126mail_login")

imprimer pp.getOptionValue("126mail_login","login_page.username")

Résultat : OK

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/Util/ParsePageObjectRepository.py

[('login_page.frame', 'id>x-URS-iframe'), ('login_page.username', "xpath>//input[@name='email']"), ('login_page.password', "xpath>//input[@name='password']"), ('login_page.loginbutton', 'id>dologin')]

{'login_page.loginbutton' : 'id>dologin', 'login_page.username' : "xpath>//input[@name='email']", 'login_page.frame' : 'id>x-URS-iframe' , 'login_page.password' : "xpath>//input[@name='password']"}

xpath>//input[@name='email']

xpath>//input[@name='email']

Processus terminé avec le code de sortie 0

Vous pouvez voir que lorsque la fonction de lecture est appelée dans le code de test, le chemin d'accès au fichier de configuration doit être saisi manuellement dans le paramètre. Il s'agit d'un caractère long. Si le chemin est modifié, il doit être modifié ici. Puisqu'il est tout encapsulé ici, il est facile de le modifier ici. Soyez diligent et configurez le chemin dans une variable.

Généralement, la variable stockant le chemin du fichier doit être placée dans le fichier var.py sous le package ProjectVar. Après cela, les chemins de tous les fichiers de configuration sont conservés sous forme de variables dans ce fichier. Le chemin relatif est utilisé pour obtenir le chemin, qui est plus sécurisé.

Étape 6 : utilisez des variables pour stocker le chemin d'accès au fichier de configuration
Créer un nouveau package ProjectVar sous le projet
Créez un nouveau fichier python de var.py sous le package ProjectVar
var.py :

#encodage=utf-8

#auteur-Xia Xiaoxu

importez-nous

#Obtenir le chemin absolu du répertoire où se trouve le projet

project_path=os.path.dirname(os.path.dirname(__file__))

#Obtenir le chemin absolu du fichier de bibliothèque d'objets de page

page_object_repository_path=project_path.decode("utf-8")+u"/conf/PageObjectRepository.ini"

si __name__=='__main__' :

    #Tester le code

    imprimer "chemin_projet :", chemin_projet

    imprimer "page_object_repository_path :",page_object_repository_path

    imprimer os.path.exists (project_path)

    imprimer os.path.exists (page_object_repository_path)

résultat:

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/ProjectVar/var.py

chemin_projet : D:/test/dataDrivenTestPractice1

chemin_page_object_repository : D:/test/dataDrivenTestPractice1/conf/PageObjectRepository.ini

Vrai

Vrai

Processus terminé avec le code de sortie 0

Testez maintenant l'exécution de la lecture du fichier de configuration dans ParsePageObjectRepository.py

ParsePageObjectRepository.py:

#encodage=utf-8

#auteur-Xia Xiaoxu

à partir de ConfigParser importer ConfigParser

à partir de ProjectVar.var import page_object_repository_path#Nouvellement ajouté

classe ParsePageObjectRepositoryConfig (objet) :

    def __init__(self):#Suppression du paramètre config_path

        self.cf=ConfigParser()#Générer l'analyseur

        self.cf.read(page_object_repository_path)#Remplacer directement par des variables

    def getItemSection(self,sectionName) :

        imprimer self.cf.items(sectionName)

        retourner dict(self.cf.items(sectionName))

    def getOptionValue(self,sectionName,optionName):#Renvoyer un dictionnaire

        print self.cf.get(sectionName,optionName)

        return self.cf.get(sectionName,optionName)

si __name__=='__main__' :

    pp=ParsePageObjectRepositoryConfig()#La variable d'adresse du fichier de configuration a été initialisée dans le constructeur

    imprimer pp.getItemSection("126mail_login")

imprimer pp.getOptionValue("126mail_login","login_page.username")

Résultat : OK

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/Util/ParsePageObjectRepository.py

[('login_page.frame', 'id>x-URS-iframe'), ('login_page.username', "xpath>//input[@name='email']"), ('login_page.password', "xpath>//input[@name='password']"), ('login_page.loginbutton', 'id>dologin')]

{'login_page.loginbutton' : 'id>dologin', 'login_page.username' : "xpath>//input[@name='email']", 'login_page.frame' : 'id>x-URS-iframe' , 'login_page.password' : "xpath>//input[@name='password']"}

xpath>//input[@name='email']

xpath>//input[@name='email']

Ensuite, corrigez les appels dans le fichier login.py et remplacez tous les paramètres qui doivent être saisis manuellement en lisant le fichier de configuration.
Modifier login.py :

#encodage=utf-8

#auteur-Xia Xiaoxu

à partir du pilote Web d'importation de sélénium

heure d'importation

à partir de selenium.webdriver.support.ui importer WebDriverWait

à partir de selenium.webdriver.common.by import Par

from selenium.common.exceptions import TimeoutException, NoSuchElementException

import traceback

from Util.ParsePageObjectRepository import *#新加

from ProjectVar.var import *#新加

class LoginPage(object):

    def __init__(self,driver):

        self.driver=driver

        self.parse_config_file=ParsePageObjectRepositoryConfig()#新加,获取配置文件信息

        self.login_page_items=self.parse_config_file.getItemSection("126mail_login")#新加

        print "self.login_page_items:",self.login_page_items

        self.wait = WebDriverWait(self.driver, 10, 0.2)  # 显示等待

    def getFrame(self):#参数去掉,在里面处理

        locateType,locateExpression=self.login_page_items['login_page.frame'].split('>')#id>x-URS-iframe

        frame=self.wait.until(lambda x: x.find_element(by=locateType,value=locateExpression))#"//iframe[@id='x-URS-iframe']"

        trame de retour

    def getUserName(self): #Supprimez les paramètres et traitez-les à l'intérieur

        LocateType, LocateExpression = self.login_page_items['login_page.username'].split('>')#xpath>//input[@name='email']

        userName=self.wait.until(lambda x: x.find_element(by=locateType,value=locateExpression))#"//input[@placeholder='Compte de messagerie ou numéro de téléphone mobile' et @name='email']"

        renvoyer le nom d'utilisateur

    def getPassword(self): #Supprimez les paramètres et traitez-les à l'intérieur

        LocateType, LocateExpression = self.login_page_items['login_page.password'].split('>')#xpath>//input[@name='password']

        password=self.wait.until(lambda x: x.find_element(by=locateType,value=locateExpression))#"//input[@placeholder='密码']"

        retourner le mot de passe

    def getLoginButton(self): #Supprimez les paramètres et traitez-les à l'intérieur

        LocateType, LocateExpression = self.login_page_items['login_page.loginbutton'].split('>') #id>dologin

        loginButton=self.wait.until(lambda x: x.find_element(by=locateType,value=locateExpression))#"//a[@id='dologin']"

        retourner le bouton de connexion

si __name__=="__main__":

    driver=webdriver.Firefox(executable_path='c:\\geckodriver')

    driver.get("http:\\mail.126.com")

    lp = Page de connexion (pilote)

    driver.switch_to.frame(lp.getFrame())

    temps.sommeil(2)

    lp.getUserName().clear()

    lp.getUserName().send_keys("xiaxiaoxu1987")

    lp.getPassword().send_keys("gloryroad")

    lp.getLoginButton().click()

    driver.switch_to.default_content()

    temps.sommeil(5)

affirmez que vous "退出" dans driver.page_source, "n'existe pas dans page_source"

Jusqu'à présent, nous avons encapsulé beaucoup de choses et mis les données de connexion dans le fichier de configuration pour les lire. Cependant, il reste encore beaucoup de chemin à parcourir avant la perfection, mais cela n'a pas d'importance. Tant que nous avons une vision claire idée, la perfection n'est qu'une question de temps. Voyons maintenant s'il y a des problèmes avec ce framework qui doivent être optimisés.
Vous pouvez constater que les deux points suivants peuvent être optimisés :

1-Dans la méthode d'obtention des éléments de la page de connexion dans le fichier login_page.py, les étapes suivantes pour rechercher des éléments peuvent être encapsulées,

self.wait.until(lambda x: x.find_element(by=locateType,value=locateExpression)), il n'est pas nécessaire d'écrire ceci dans chaque méthode de recherche d'éléments, et cette étape de recherche d'éléments est en cours d'ajout de contacts au compte Il sera également utilisé dans les fonctions.Il sera beaucoup plus pratique d'encapsuler la méthode de recherche d'éléments.

2-Deuxièmement, lors de l'exécution de l'opération de connexion, nous saisissons manuellement les informations de nom d'utilisateur et de mot de passe. Cela peut également être encapsulé. Comment l'encapsuler ? Chaque méthode du fichier login.py initial obtient les informations de connexion. Pour les éléments requis, nous appelez manuellement ces méthodes lors de l'exécution de l'opération de connexion. Après avoir obtenu les éléments, entrez des caractères ou cliquez pour terminer l'opération de connexion. Ces étapes peuvent ensuite être effectuées dans un autre fichier. L'encapsulation, pour parler franchement, consiste à encapsuler la méthode d'obtention de chaque élément dans login_page pour réaliser la fonction de connexion. Vous n'avez pas besoin d'organiser vous-même les méthodes dispersées à chaque fois. Mettez-le dans une boîte. Le nom de la boîte est login. À chaque fois, exécutez simplement cette boîte, ne vous inquiétez pas les détails à l'intérieur, tous les emballages sont les mêmes.

Étape 7 : encapsuler la fonction de recherche d'éléments et encapsuler davantage la fonction de connexion

Comme vous pouvez le voir dans la structure initiale du cadre, la méthode de recherche d'éléments peut être placée dans le package Util.

Créez un nouveau fichier ObjectMap.py dans le package Util
ObjectMap.py :

#encodage=utf-8

#auteur-Xia Xiaoxu

à partir de selenium.webdriver.support.ui importer WebDriverWait

#Obtenir un objet à un seul élément

def getElement(pilote,locateType,locateExpression) :

    essayer:

        element=WebDriverWait(driver,10).until(lambda x:x.find_element(by=locateType,value=locateExpression))

        élément de retour

    sauf exception,e :

        élever e

#Obtenez plusieurs objets d'élément de page identiques et renvoyez-les sous forme de liste

def getElements(pilote,locateType,locatorExpression) :

    essayer:

        elements=WebDriverWait(driver,5).until(lambda x:x.find_elements(by=locateType,value=locateExpression))

        éléments de retour

    sauf exception,e :

        élever e

si __name__=="__main__":

    #Tester le code

    à partir du pilote Web d'importation de sélénium

    driver=webdriver.Firefox(executable_path='c:\\geckodriver')

    driver.get('http://www.baidu.com')

    searchBox=getElement(driver,"xpath","//input[@id='kw']")

    pilote.quit()

Résultat : OK

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/Util/ObjectMap.py

Processus terminé avec le code de sortie 0

À ce stade, la méthode de recherche d'éléments est encapsulée. Modifions Login_Page.py pour appeler la méthode ObjectMap afin d'implémenter chaque méthode de recherche d'éléments et encapsulons l'action de connexion.
Login_page.py :

#encodage=utf-8

#auteur-Xia Xiaoxu

à partir du pilote Web d'importation de sélénium

heure d'importation

à partir de selenium.webdriver.support.ui importer WebDriverWait

à partir de selenium.webdriver.common.by import Par

à partir de selenium.common.exceptions importer TimeoutException, NoSuchElementException

traçage des importations

à partir de l'importation de Util.ParsePageObjectRepository *

à partir de l'importation ProjectVar.var *

à partir de l'importation Util.ObjectMap *

classe LoginPage (objet):

    def __init__ (soi, pilote) :

        self.driver=pilote

        self.parse_config_file=ParsePageObjectRepositoryConfig()

        self.login_page_items=self.parse_config_file.getItemSection("126mail_login")

        imprimer "self.login_page_items :",self.login_page_items

        self.wait = WebDriverWait(self.driver, 10, 0.2) # Afficher l'attente

    def getFrame(soi) :

        LocateType,locateExpression=self.login_page_items['login_page.frame'].split('>')#id>x-URS-iframe

        frame=getElement(self.driver,locateType,locateExpression)#"//iframe[@id='x-URS-iframe']"

        trame de retour

    def getUserName (soi) :

        LocateType, LocateExpression = self.login_page_items['login_page.username'].split('>')#xpath>//input[@name='email']

        userName=getElement(self.driver,locateType,locateExpression)#"//input[@placeholder='Compte de messagerie ou numéro de téléphone portable' et @name='email']"

        renvoyer le nom d'utilisateur

    def getPassword(soi) :

        LocateType, LocateExpression = self.login_page_items['login_page.password'].split('>')#xpath>//input[@name='password']

        password=getElement(self.driver,locateType,locateExpression)#"//input[@placeholder='密码']"

        retourner le mot de passe

    def getLoginButton (soi) :

        LocateType, LocateExpression = self.login_page_items['login_page.loginbutton'].split('>') #id>dologin

        loginButton=getElement(self.driver,locateType,locateExpression)#"//a[@id='dologin']"

        retourner le bouton de connexion

    connexion par défaut (auto):

        self.driver.switch_to.frame(self.getFrame())

        self.getUserName().clear()

        self.getUserName().send_keys("xiaxiaoxu1987")

        self.getPassword().send_keys("gloryroad")

        self.getLoginButton().click()

if __name__=="__main__":

    #测试代码

    driver=webdriver.Firefox(executable_path='c:\\geckodriver')

    driver.get("http:\\mail.126.com")

    lp=LoginPage(driver)

lp.login()

结果:可以登录

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/PageObject/Login_Page.py

self.login_page_items: {'login_page.loginbutton': 'id>dologin', 'login_page.username': "xpath>//input[@name='email']", 'login_page.frame': 'id>x-URS-iframe', 'login_page.password': "xpath>//input[@name='password']"}

Process finished with exit code 0

下面我们把login函数的封装从Login_page.py中挪出去,作为单独的一个文件存在,把方法和调用分隔开,以后如果有变动,修改login_page.py就可以了。

步骤8—单独封装login方法
在工程下新建一个Action的包
在Action包下新建login.py
Login.py:

#encoding=utf-8

#author-夏晓旭

from PageObject.Login_Page import *

from selenium import webdriver

def login (pilote, nom d'utilisateur, mot de passe) :

    lp = Page de connexion (pilote)

    driver.switch_to.frame(lp.getFrame())

    lp.getUserName().clear()

    lp.getUserName().send_keys(nom d'utilisateur)

    lp.getPassword().send_keys(mot de passe)

    lp.getLoginButton().click()

si __name__=='__main__' :

    #Tester le code

    driver=webdriver.Firefox(executable_path='c:\\geckodriver')

    driver.get("http://mail.126.com")

    connexion (pilote, "xiaxiaoxu1987", "gloryroad")

Résultat : connexion réussie

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/Action/login.py

self.login_page_items : {'login_page.loginbutton' : 'id>dologin', 'login_page.username' : "xpath>//input[@name='email']", 'login_page.frame' : 'id>x- URS-iframe', 'login_page.password' : "xpath>//input[@name='password']"}

Processus terminé avec le code de sortie 0

À ce stade, la fonction de connexion est essentiellement encapsulée et les données et le programme sont séparés. Jetons un coup d'œil à l'encapsulation de l'ajout de contacts pour réaliser la séparation des données et du programme étape par étape. Les opérations d'ajout de contacts ont été mises en AddressBook.py avant. , mais la situation est la même que celle de login_page.py au début. L'opération de recherche d'éléments et la lecture des données du fichier de configuration n'ont pas encore été effectuées. Commençons par cela.
Étape 9 : Encapsuler l'opération d'ajout de contact
Idée:

Dans AddressBook.py, encapsulez chaque élément nécessaire pour ajouter une page de contact dans une méthode, recherchez les données XPath requises pour chaque élément et placez-les dans le fichier de configuration, puis utilisez une fonction pour appeler les méthodes de ces éléments pour implémenter les caractères d'entrée. ou cliquez sur les opérations. Implémentez la fonction d'ajout de contacts

Carnet d'adresses.py:

#encodage=utf-8

#auteur-Xia Xiaoxu

à partir du pilote Web d'importation de sélénium

heure d'importation

à partir de selenium.webdriver.support.ui importer WebDriverWait

à partir de selenium.webdriver.common.by import Par

à partir de selenium.common.exceptions importer TimeoutException, NoSuchElementException

traçage des importations

à partir de l'importation PageObject.Login_Page *

à partir de l'importation Action.login *

classe Carnet d'adresses (objet):

    def __init__ (soi, pilote) :

        self.driver=pilote

        self.parse_config_file=ParsePageObjectRepositoryConfig()

        self.address_book_page=self.parse_config_file.getItemsFromSection("126mail_homepage")

        imprimer "self.address_book_page:",self.address_book_page

        self.address_book_page_itmes=self.parse_config_file.getItemsFromSection("126mail_addcontactspage")

        imprimer "self.address_book_page_itmes:", self.address_book_page_itmes

    def adresse_book_link(soi) :

        LocateType,locateExpression = self.address_book_page['home_page.addressbook'].split(">")

        imprimer le type de localisation, localiser l'expression

        return getElement(self.driver,"xpath","//div[text()='Carnet d'adresses']")

    def add_contact_button(soi) :

        LocateType,locateExpression=self.address_book_page_itmes['addcontacts_page.createcontactsbtn'].split(">")

        imprimer le type de localisation, localiser l'expression

        retourner getElement(self.driver,locateType,locateExpression)

    def nom_contact (soi) :

        LocateType,locateExpression=self.address_book_page_itmes['addcontacts_page.contactpersonname'].split(">")

        imprimer le type de localisation, localiser l'expression

        retourner getElement (self.driver, LocateType, LocateExpression)

    def contact_email(soi) :

        LocateType, LocateExpression = self.address_book_page_itmes['addcontacts_page.contactpersonemail'].split(">")

        imprimer le type de localisation, localiser l'expression

        retourner getElement (self.driver, LocateType, LocateExpression)

    def contact_is_star(soi) :

        LocateType, LocateExpression = self.address_book_page_itmes['addcontacts_page.starcontacts'].split(">")

        imprimer le type de localisation, localiser l'expression

        retourner getElement (self.driver, LocateType, LocateExpression)

    def contact_mobile(soi) :

        LocateType, LocateExpression = self.address_book_page_itmes['addcontacts_page.contactpersonmobile'].split(">")

        imprimer le type de localisation, localiser l'expression

        retourner getElement (self.driver, LocateType, LocateExpression)

    def contact_other_info(soi) :

        LocateType, LocateExpression = self.address_book_page_itmes['addcontacts_page.contactpersoncomment'].split(">")

        imprimer le type de localisation, localiser l'expression

        retourner getElement (self.driver, LocateType, LocateExpression)

    def contact_save_button(soi) :

        LocateType, LocateExpression = self.address_book_page_itmes['addcontacts_page.savecontaceperson'].split(">")

        imprimer le type de localisation, localiser l'expression

        retourner getElement (self.driver, LocateType, LocateExpression)

si __name__=="__main__":

    driver = webdriver.Firefox(executable_path='c:\\geckodriver')

    driver.get("http://mail.126.com")

    connexion (pilote, "xiaxiaoxu1987", "gloryroad")

    carnet d'adresses = Carnet d'adresses (pilote)

    temps.sommeil(5)

    carnet d'adresses.address_book_link().click()

    carnet d'adresses.add_contact_button().click()

    carnet d'adresses.contact_name().send_keys("sam")

    carnet d'adresses.contact_email().send_keys("[email protected]")

    carnet d'adresses.contact_is_star().click()

    carnet d'adresses.contact_mobile().send_keys("18142244444")

    carnet d'adresses.contact_other_info().send_keys("moi-même")

carnet d'adresses.contact_save_button().click()

Résultat : OK

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/PageObject/AddressBook.py

self.login_page_items : {'login_page.loginbutton' : 'id>dologin', 'login_page.username' : "xpath>//input[@name='email']", 'login_page.frame' : 'id>x- URS-iframe', 'login_page.password' : "xpath>//input[@name='password']"}

self.address_book_page : {'home_page.addressbook' : "xpath>//div[text()='\xe9\x80\x9a\xe8\xae\xaf\xe5\xbd\x95']"}

self.address_book_page_itmes : {'addcontacts_page.createcontactsbtn' : "xpath>//span[text()='\xe6\x96\xb0\xe5\xbb\xba\xe8\x81\x94\xe7\xb3\xbb\xe4\ xba\xba']", 'addcontacts_page.contactpersonmobile' : "xpath>//*[@id='iaddress_TEL_wrap']//dd//input", 'addcontacts_page.contactpersonemail' : "xpath>//*[@id ='iaddress_MAIL_wrap']//input", 'addcontacts_page.contactpersoncomment' : 'xpath>//textarea', 'addcontacts_page.contactpersonname' : "xpath>//a[@title='\xe7\xbc\x96\xe8\ xbe\x91\xe8\xaf\xa6\xe7\xbb\x86\xe5\xa7\x93\xe5\x90\x8d']/preceding-sibling::div/input", 'addcontacts_page.savecontaceperson': "xpath>/ /span[.='\xe7\xa1\xae \xe5\xae\x9a']", 'addcontacts_page.starcontacts' :"xpath>//span[text()='\xe8\xae\xbe\xe4\xb8\xba\xe6\x98\x9f\xe6\xa0\x87\xe8\x81\x94\xe7\xb3\xbb\xe4 \xba\xba']/preceding-sibling::span/b"}

xpath //div[text()='Carnet d'adresses']

xpath //span[text()='Nouveau contact']

xpath //a[@title='Modifier le nom détaillé']/preceding-sibling::div/input

xpath //*[@id='iaddress_MAIL_wrap']//input

xpath //span[text()='Définir comme contact étoile']/preceding-sibling::span/b

xpath //*[@id='iaddress_TEL_wrap']//dd//input

XPath //zone de texte

xpath //span[.='OK']

Maintenant, nous avons encapsulé l'opération d'ajout de chaque élément de la page de contact et l'avons appelé dans le code de test. Tout comme l'encapsulation de la fonction de connexion, nous avons encapsulé l'opération d'ajout de chaque élément de la page de contact dans un autre fichier. , appelez-le simplement directement dans le programme principal, ce qui est pratique à utiliser.
Étape 10 : encapsulez séparément la fonction d'ajout de contact du carnet d'adresses
Créez un nouveau fichier add_contact.py sous le package Action
add_contact.py :

#encodage=utf-8

#auteur-Xia Xiaoxu

à partir de l'importation PageObject.AddressBook *

à partir du pilote Web d'importation de sélénium

def add_contact (pilote):

    driver.switch_to.default_content()

    carnet d'adresses = Carnet d'adresses (pilote)

    carnet d'adresses.address_book_link().click()

    carnet d'adresses.add_contact_button().click()

    carnet d'adresses.contact_name().send_keys("sam")

    carnet d'adresses.contact_email().send_keys("[email protected]")

    carnet d'adresses.contact_is_star().click()

    carnet d'adresses.contact_mobile().send_keys("18142244444")

    carnet d'adresses.contact_other_info().send_keys("moi-même")

    carnet d'adresses.contact_save_button().click()

si __name__=='__main__' :

    driver=webdriver.Firefox(executable_path="c:\\geckodriver")

    driver.get("http://mail.126.com")

    connexion (pilote, "xiaxiaoxu1987", "gloryroad")

    add_contact (pilote)

   

résultat:

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/Action/add_contact.py

self.login_page_items : {'login_page.loginbutton' : 'id>dologin', 'login_page.username' : "xpath>//input[@name='email']", 'login_page.frame' : 'id>x- URS-iframe', 'login_page.password' : "xpath>//input[@name='password']"}

Processus terminé avec le code de sortie 0

Encapsuler davantage, remplacer la partie d'entrée par des paramètres

#encodage=utf-8

#auteur-Xia Xiaoxu

à partir de l'importation PageObject.AddressBook *

à partir du pilote Web d'importation de sélénium

def add_contact(driver,name="",email="",is_star=True,mobile="",otherinfo="") :

    driver.switch_to.default_content()

    carnet d'adresses = Carnet d'adresses (pilote)

    carnet d'adresses.address_book_link().click()

    carnet d'adresses.add_contact_button().click()

    carnet d'adresses.contact_name().send_keys(nom)

    carnet d'adresses.contact_email().send_keys(email)

    si is_star==Vrai :

        carnet d'adresses.contact_is_star().click()

    carnet d'adresses.contact_mobile().send_keys(mobile)

    carnet d'adresses.contact_other_info().send_keys(autresinformations)

    carnet d'adresses.contact_save_button().click()

si __name__=='__main__' :

    driver=webdriver.Firefox(executable_path="c:\\geckodriver")

    driver.get("http://mail.126.com")

    connexion (pilote, "xiaxiaoxu1987", "gloryroad")

    add_contact(driver,"xiaxiaoxu","[email protected]",True,"13333334444","gloryroad")

pilote.quit()

Résultat : OK

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/Action/add_contact.py

self.login_page_items : {'login_page.loginbutton' : 'id>dologin', 'login_page.username' : "xpath>//input[@name='email']", 'login_page.frame' : 'id>x- URS-iframe', 'login_page.password' : "xpath>//input[@name='password']"}

Processus terminé avec le code de sortie 0

À ce stade, nous avons encapsulé la plupart des fonctions. Essayons maintenant d'appeler ces fonctions dans le programme principal :
TestScript.py :

#encodage=utf-8

#auteur-Xia Xiaoxu

à partir du pilote Web d'importation de sélénium

heure d'importation

à partir de selenium.webdriver.support.ui importer WebDriverWait

à partir de selenium.webdriver.common.by import Par

à partir de selenium.common.exceptions importer TimeoutException, NoSuchElementException

traçage des importations

à partir de l'importation PageObject.Login_Page *

à partir de l'importation PageObject.AddressBook *

depuis l'importation Action.add_contact *

à partir de l'importation Action.login *

driver=webdriver.Firefox(executable_path='c:\\geckodriver')

driver.get('http://mail.126.com')

connexion (pilote, "xiaxiaoxu1987", "gloryroad")

add_contact(driver,"xiaxiaoxu","[email protected]",True,"13333334444","gloryroad")

pilote.quit()

Résultat : ça marche bien.

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/TestScript/TestScript.py

Processus terminé avec le code de sortie 0

À en juger par les appels dans le programme principal, certaines données doivent encore être saisies manuellement, telles que les noms d'utilisateur, les mots de passe et les informations de contact qui doivent être ajoutées. Si vous devez ajouter plusieurs contacts, vous devez les saisir. plusieurs fois. Étape suivante Voyons comment séparer cette partie des données du programme et l'enregistrer dans un fichier. Cette fois, nous la mettrons dans Excel, puis utiliserons la méthode d'exploitation d'Excel pour extraire les données.
Étape 11-Encapsuler les opérations Excel
Créez un fichier Excel et mettez les informations du compte 126 dans la première feuille.

La deuxième feuille contient les contacts :

Créez un nouveau package TestData sous le projet et placez le fichier Excel sous le package.
Excel.py :

#encodage=utf-8

#auteur-Xia Xiaoxu

# encodage=utf-8

depuis openpyxl importer load_workbook

à partir d'openpyxl.styles, importez la bordure, le côté, la police

heure d'importation

à partir de l'importation ProjectVar.var *

classe parseExcel (objet):

    def __init__(soi, excelPath) :

        self.excelPath = excelPath

        self.workbook = load_workbook(excelPath) # pour Excel

        self.sheet = self.workbook.active # Récupère la première feuille

        self.font = Police (couleur = Aucun)

        self.colorDict = {"rouge": 'FFFF3030', "vert": 'FF008B00'}

    #Définissez l'objet de feuille actuellement à utiliser et utilisez l'index pour obtenir la feuille correspondante

    def set_sheet_by_index(self, sheet_index):

        nom_feuille = self.workbook.get_sheet_names()[sheet_index]

        self.sheet = self.workbook.get_sheet_by_name(sheet_name)

        retourner self.sheet

    # Récupère le nom de la feuille par défaut actuelle

    def get_default_sheet(soi) :

        retourner self.sheet.title

    #Définissez l'objet de feuille actuellement à utiliser et utilisez le nom de la feuille pour obtenir la feuille correspondante

    def set_sheet_by_name(self, sheet_name) :

        feuille = self.workbook.get_sheet_by_name(sheet_name)

        self.sheet = feuille

        retourner self.sheet

    # Obtenez le nombre maximum de lignes dans la feuille par défaut

    def get_max_row_no(self):

        retourner self.sheet.max_row

    # Obtenez le nombre maximum de colonnes de la feuille par défaut

    def get_max_col_no(self):

        retourner self.sheet.max_column

    # Obtenez le numéro de ligne minimum (de départ) de la feuille par défaut

    def get_min_row_no(self):

        retourner self.sheet.min_row

    # Obtenez le numéro de colonne minimum (de départ) de la feuille par défaut

    def get_min_col_no(self):

        retourner self.sheet.min_column

    # Récupère tous les objets lignes de la feuille par défaut,

    def get_all_rows(self):

        liste de retour (self.sheet.iter_rows())

        # la liste de retour (self.rows) peut également être utilisée

    # Récupère tous les objets de colonne dans la feuille par défaut

    def get_all_cols(self):

        liste de retour (self.sheet.iter_cols())

        # la liste de retour (self.sheet.columns) peut également être utilisée

    # Récupère une colonne de la feuille par défaut, la première colonne commence à 0

    def get_single_col(self, col_no) :

        retourner self.get_all_cols()[col_no]

    # Récupère une certaine ligne de la feuille par défaut, la première ligne commence à 0

    def get_single_row(self, row_no) :

        retourner self.get_all_rows()[row_no]

    # À partir de la feuille par défaut, obtenez la cellule spécifiée via le numéro de ligne et le numéro de colonne. Notez que le numéro de ligne et le numéro de colonne commencent à 1

    def get_cell(self, row_no, col_no) :

        retourner self.sheet.cell(row=row_no, column=col_no)

    # À partir de la feuille par défaut, obtenez le contenu de la cellule spécifiée via le numéro de ligne et le numéro de colonne. Notez que le numéro de ligne et le numéro de colonne commencent à 1

    def get_cell_content(self, row_no, col_no) :

        retourner self.sheet.cell(row=row_no, column=col_no).value

    # À partir de la feuille par défaut, écrivez le contenu spécifié dans la cellule spécifiée via le numéro de ligne et le numéro de colonne. Notez que le numéro de ligne et le numéro de colonne commencent à 1

    # Lors de l'appel de cette méthode, Excel ne doit pas être ouvert.

    def write_cell_content(self, row_no, col_no, content, font=None) :

        self.sheet.cell(row=row_no, column=col_no).value = contenu

        self.workbook.save(self.excelPath)

        retourner self.sheet.cell(row=row_no, column=col_no).value

    # À partir de la feuille par défaut, écrivez la date actuelle dans la cellule spécifiée via le numéro de ligne et le numéro de colonne. Notez que le numéro de ligne et le numéro de colonne commencent à 1

    # Lors de l'appel de cette méthode, Excel ne doit pas être ouvert.

    def write_cell_current_time(self, row_no, col_no) :

        heure1 = heure.strftime("%Y-%m-%d %H:%M:%S")

        self.sheet.cell(row=row_no, column=col_no).value = str(time1)

        self.workbook.save(self.excelPath)

        retourner self.sheet.cell(row=row_no, column=col_no).value

    def save_excel_file(self):

        self.workbook.save(self.excelPath)

si __name__ == '__main__' :

    #Tester le code

    p = parseExcel (test_data_excel_path)

    print u"Obtenir la feuille par défaut :", p.get_default_sheet()

    print u"Définir l'index de la feuille sur 1", p.set_sheet_by_index(1)

    print u"Obtenir la feuille par défaut :", p.get_default_sheet()

    print u"Définir l'index de la feuille à 0", p.set_sheet_by_index(0)

    print u"Obtenir la feuille par défaut :", p.get_default_sheet()

    print u"Nombre maximum de lignes :", p.get_max_row_no()

    print u"Nombre maximum de colonnes :", p.get_max_col_no()

    print u"Numéro minimum de ligne de départ :", p.get_min_row_no()

    print u"Nombre minimum de colonnes de départ :", p.get_min_col_no()

    print u"Tous les objets de ligne :", p.get_all_rows()

    print u"Tous les objets de colonne :", p.get_all_cols()

    print u"Obtenir une certaine colonne (2) :", p.get_single_col(2)

    print u"Obtenir une certaine ligne(1) :", p.get_single_row(1)

    print u"Obtenir le numéro de ligne et le numéro de colonne (2,2) cellule :", p.get_cell(2, 2)

    print u"Obtenir le contenu de la cellule du numéro de ligne et du numéro de colonne (2, 2)", p.get_cell_content(2, 2)

    print u"le numéro de ligne et de colonne écrit le contenu (11,11) : 'xiaxiaoxu'", p.write_cell_content(11, 11, 'xiaxiaoxu') #

    print u"Le numéro de ligne et le numéro de colonne sont écrits dans la date actuelle (13,13) :", p.write_cell_current_time(13, 13)

Résultat : OK

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/Util/Excel.py

Récupérer la fiche par défaut : Contact

Définir l'index de la feuille sur 1 <Worksheet "\u8054\u7cfb\u4eba">

Récupérer la fiche par défaut : Contact

Définir l'index de la feuille sur 0 <Feuille de travail "126\u8d26\u53f7">

Obtenez la feuille par défaut : 126 comptes

Nombre maximum de lignes : 3

Nombre maximum de colonnes : 6

Nombre minimum de lignes de départ : 1

Nombre minimum de colonnes de départ : 1

所有行对象: [(<Cellule u'126\u8d26\u53f7'.A1>, <Cellule u'126\u8d26\u53f7'.B1>, <Cellule u'126\u8d26\u53f7'.C1>, <Cellule u'126\u8d26\u53f7'.D1>, <Cellule u'126\u8d26\u53f7'.E1>, <Cellule u'126\u8d26\u53f7'.F1>), (<Cellule u'126\u8d26\ u53f7'.A2>, <Cellule u'126\u8d26\u53f7'.B2>, <Cellule u'126\u8d26\u53f7'.C2>, <Cellule u'126\u8d26\u53f7'.D2>, <Cellule u'126\u8d26\u53f7'.E2>, <Cellule u'126\u8d26\u53f7'.F2>), (<Cellule u'126\u8d26\u53f7'.A3>, <Cellule u'126\u8d26\ u53f7'.B3>, <Cellule u'126\u8d26\u53f7'.C3>, <Cellule u'126\u8d26\u53f7'.D3>, <Cellule u'126\u8d26\u53f7'.E3>, <Cellule u'126\u8d26\u53f7'.F3>)]

所有列对象: [(<Cellule u'126\u8d26\u53f7'.A1>, <Cellule u'126\u8d26\u53f7'.A2>, <Cellule u'126\u8d26\u53f7'.A3>), ( <Cellule u'126\u8d26\u53f7'.B1>, <Cellule u'126\u8d26\u53f7'.B2>, <Cellule u'126\u8d26\u53f7'.B3>), (<Cellule u'126\ u8d26\u53f7'.C1>, <Cellule u'126\u8d26\u53f7'.C2>, <Cellule u'126\u8d26\u53f7'.C3>), (<Cellule u'126\u8d26\u53f7'.D1 >, <Cellule u'126\u8d26\u53f7'.D2>, <Cellule u'126\u8d26\u53f7'.D3>), (<Cellule u'126\u8d26\u53f7'.E1>, <Cellule u' 126\u8d26\u53f7'.E2>, <Cellule u'126\u8d26\u53f7'.E3>), (<Cellule u'126\u8d26\u53f7'.F1>, <Cellule u'126\u8d26\u53f7' .F2>, <Cellule u'126\u8d26\u53f7'.F3>)]

Obtenez une certaine colonne (2) : (<Cell u'126\u8d26\u53f7'.C1>, <Cell u'126\u8d26\u53f7'.C2>, <Cell u'126\u8d26\u53f7'.C3> )

获取某一行(1): (<Cellule u'126\u8d26\u53f7'.A2>, <Cellule u'126\u8d26\u53f7'.B2>, <Cellule u'126\u8d26\u53f7'.C2>, <Cellule u'126\u8d26\u53f7'.D2>, <Cellule u'126\u8d26\u53f7'.E2>, <Cellule u'126\u8d26\u53f7'.F2>)

Obtenez le numéro de ligne et le numéro de colonne (2,2) de la cellule : <Cell u'126\u8d26\u53f7'.B2>

Obtenez le contenu des cellules du numéro de ligne et du numéro de colonne (2,2) xiaxiaoxu1987

Le numéro de ligne et le numéro de colonne écrivent le contenu (11,11) : 'xiaxiaoxu' xiaxiaoxu

Le numéro de ligne et le numéro de colonne sont écrits dans la date actuelle (13,13) : 2018-07-10 21:28:14

Processus terminé avec le code de sortie 0

À ce stade, l’opération Excel a été encapsulée. Essayons de lire les données dans le programme principal.
TestScript.py :

#encodage=utf-8

#auteur-Xia Xiaoxu

à partir du pilote Web d'importation de sélénium

heure d'importation

à partir de selenium.webdriver.support.ui importer WebDriverWait

à partir de selenium.webdriver.common.by import Par

à partir de selenium.common.exceptions importer TimeoutException, NoSuchElementException

traçage des importations

à partir de l'importation PageObject.Login_Page *

à partir de l'importation PageObject.AddressBook *

depuis l'importation Action.add_contact *

à partir de l'importation Action.login *

à partir de l'importation ProjectVar.var *

à partir de l'importation Util.Excel *

driver=webdriver.Firefox(executable_path='c:\\geckodriver')

driver.get('http://mail.126.com')

pe=parseExcel(test_data_excel_path)

pe.set_sheet_by_name(u"Compte 126")

imprimer pe.get_default_sheet()

lignes=pe.get_all_rows()[1:]

pour l'identifiant, ligne dans enumerate (lignes):

    si ligne[4].value =='y' :

        nom d'utilisateur = ligne[1].value

        mot de passe = ligne[2].value

        imprimer le nom d'utilisateur, le mot de passe

        essayer:

            login (pilote, nom d'utilisateur, mot de passe)

            pe.set_sheet_by_name(u"Contact")

            imprimer pe.get_default_sheet()

            rows1=pe.get_all_rows()[1:]

            imprimer "lignes1 :", lignes1

            pour id1,ligne dans enumerate(rows1):

                si row[7].value == 'y' :

                    essayer:

                        #print row[1].value,row[2].value,row[3].value,row[4].value,row[5].value

                        #print "exécuter1"

                        add_contact (pilote, ligne [1]. valeur, ligne [2]. valeur, ligne [3]. valeur, ligne [4]. valeur, ligne [5]. valeur)

                        imprimer "assert word:",row[6].value dans driver.page_source

                        imprimer la ligne[6].value

                        pe.write_cell_content(id1+2,10,"pass")

                    sauf exception,e :

                        imprimer u "Message d'exception :", e.message

                        pe.write_cell_content(id1+2,10,"échec")

                autre:

                    pe.write_cell_content(id1+2,10,u"忽略")

                    continuer

        sauf exception,e :

            pe.set_sheet_by_name(u"Compte 126")

            imprimer u"Message d'exception :",e

            pe.write_cell_content(id+2,5,"échec")

    autre:

        pe.set_sheet_by_name(u"Compte 126")

        pe.write_cell_content(id+2,6,u"忽略")

        continuer

Résultat : exécution ok

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/TestScript/TestScript.py

126compte

xiaxiaoxu1987 route de la gloire

Personne de contact

lignes 1 : [(<Cellule u'\u8054\u7cfb\u4eba'.A2>, <Cellule u'\u8054\u7cfb\u4eba'.B2>, <Cellule u'\u8054\u7cfb\u4eba'.C2>, < Cellule u'\u8054\u7cfb\u4eba'.D2>, <Cellule u'\u8054\u7cfb\u4eba'.E2>, <Cellule u'\u8054\u7cfb\u4eba'.F2>, <Cellule u'\u8054 \u7cfb\u4eba'.G2>, <Cellule u'\u8054\u7cfb\u4eba'.H2>, <Cellule u'\u8054\u7cfb\u4eba'.I2>, <Cellule u'\u8054\u7cfb\u4eba' .J2>), (<Cellule u'\u8054\u7cfb\u4eba'.A3>, <Cellule u'\u8054\u7cfb\u4eba'.B3>, <Cellule u'\u8054\u7cfb\u4eba'.C3> , <Cellule u'\u8054\u7cfb\u4eba'.D3>, <Cellule u'\u8054\u7cfb\u4eba'.E3>, <Cellule u'\u8054\u7cfb\u4eba'.F3>, <Cellule u' \u8054\u7cfb\u4eba'.G3>, <Cellule u'\u8054\u7cfb\u4eba'.H3>,<Cellule u'\u8054\u7cfb\u4eba'.I3>, <Cellule u'\u8054\u7cfb\u4eba'.J3>), (<Cellule u'\u8054\u7cfb\u4eba'.A4>, <Cellule u'\u8054\u7cfb\u4eba'.A4> '\u8054\u7cfb\u4eba'.B4>, <Cellule u'\u8054\u7cfb\u4eba'.C4>, <Cellule u'\u8054\u7cfb\u4eba'.D4>, <Cellule u'\u8054\u7cfb \u4eba'.E4>, <Cellule u'\u8054\u7cfb\u4eba'.F4>, <Cellule u'\u8054\u7cfb\u4eba'.G4>, <Cellule u'\u8054\u7cfb\u4eba'.H4 >, <Cellule u'\u8054\u7cfb\u4eba'.I4>, <Cellule u'\u8054\u7cfb\u4eba'.J4>, (<Cellule u'\u8054\u7cfb\u4eba'.A5>, < Cellule u'\u8054\u7cfb\u4eba'.B5>, <Cellule u'\u8054\u7cfb\u4eba'.C5>, <Cellule u'\u8054\u7cfb\u4eba'.D5>, <Cellule u'\u8054 \u7cfb\u4eba'.E5>, <Cellule u'\u8054\u7cfb\u4eba'.F5>,<Cellule u'\u8054\u7cfb\u4eba'.G5>, <Cellule u'\u8054\u7cfb\u4eba'.H5>, <Cellule u'\u8054\u7cfb\u4eba'.I5>, <Cellule u'\ u8054\u7cfb\u4eba'.J5>)]

affirmer le mot : vrai

[email protected]

affirmer le mot : vrai

John Doe

Processus terminé avec le code de sortie 0

Résultats Excel :

À ce stade, la plupart des fonctions du framework ont ​​été encapsulées. Ensuite, construisons le module de journalisation afin que le programme puisse imprimer des journaux lors de son exécution.

Étape 12 : Ajouter le module de journal
Créez un nouveau fichier de configuration du journal Logger.conf sous le package Conf, qui configure l'enregistreur, le processeur et le formateur. Les détails spécifiques du journal seront répertoriés plus tard.

#logger.conf
############################################# #
[loggers]
keys=root,example01,example02
[logger_root]
level=DEBUG
handlers=hand01,hand02

[logger_example01]
handlers=hand01,hand02
qualname=example01
propagate=0

[logger_example02]
handlers=hand01,hand03
qualname=example02
propagate=0

###############################################
[gestionnaires]
clés = hand01, hand02, hand03

[handler_hand01]
class =
niveau StreamHandler = INFO
formatter = form01
args = (sys.stderr,)

[handler_hand02]
classe =
niveau FileHandler = DEBUG
formatter=form01
args=('DataDrivenFrameWork.log', 'a')

[handler_hand03]
class=handlers.RotatingFileHandler
level=INFO
formatter=form01
args=('DataDrivenFrameWork.log', 'a', 10*1024*1024, 5 )

###############################################
[formatteurs ]
clés=form01,form02

[formatter_form01]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s datefmt=%Y-%m-%
d %H:%M:%S

[formatter_form02]
format=%(name)-12s : %(levelname)-8s %(message)s
datefmt=%Y-%m-%d %H:%M:%S

Créez un nouveau fichier log.py sous le package Util pour encapsuler l'opération de journalisation
Log.py :

#encodage=utf-8

#auteur-Xia Xiaoxu

journalisation des importations

importer le fichier logging.config

à partir de l'importation ProjectVar.var *

#Lire le fichier de configuration du journal

logging.config.fileConfig(chemin_projet+"\\Conf\\Logger.conf")

#Sélectionnez un format de journal

logger=logging.getLogger("exemple02")

erreur def (message) :

    #Imprimer les informations sur le niveau de débogage

    enregistreur.erreur (message)

informations de définition (message) :

    #Imprimer les informations au niveau des informations

    logger.info (message)

avertissement def (message) :

    #Imprimer les informations sur le niveau d'avertissement

    enregistreur.avertissement (message)

si __name__=="__main__":

    #Tester le code

    info("salut")

    print "chemin du fichier de configuration :", chemin_projet+"\\Conf\\Logger.conf"

    erreur("monde!")

    avertissement("gloryroad!")

Résultat : OK

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/Util/log.py

2018-07-11 21:32:12 log.py[line:19] INFO salut

chemin du fichier de configuration : D:\test\dataDrivenTestPractice1\Conf\Logger.conf

2018-07-11 21:32:12 log.py[line:15] ERREUR monde !

2018-07-11 21:32:12 log.py[line:23] AVERTISSEMENT Gloryroad !

Processus terminé avec le code de sortie 0

L’encapsulation du log est maintenant ok. Modifions le programme principal et appelons le log.
TestScript.py :

#encodage=utf-8

#auteur-Xia Xiaoxu

à partir du pilote Web d'importation de sélénium

heure d'importation

à partir de selenium.webdriver.support.ui importer WebDriverWait

à partir de selenium.webdriver.common.by import Par

à partir de selenium.common.exceptions importer TimeoutException, NoSuchElementException

traçage des importations

à partir de l'importation PageObject.Login_Page *

à partir de l'importation PageObject.AddressBook *

depuis l'importation Action.add_contact *

à partir de l'importation Action.login *

à partir de l'importation ProjectVar.var *

à partir de l'importation Util.Excel *

à partir de l'importation Util.log *

driver=webdriver.Firefox(executable_path='c:\\geckodriver')

driver.get('http://mail.126.com')

pe=parseExcel(test_data_excel_path)

pe.set_sheet_by_name(u"Compte 126")

imprimer pe.get_default_sheet()

lignes=pe.get_all_rows()[1:]

pour l'identifiant, ligne dans enumerate (lignes):

    si ligne[4].value =='y' :

        nom d'utilisateur = ligne[1].value

        mot de passe = ligne[2].value

        imprimer le nom d'utilisateur, le mot de passe

        essayer:

            login (pilote, nom d'utilisateur, mot de passe)

            pe.set_sheet_by_name(u"Contact")

            imprimer pe.get_default_sheet()

            rows1=pe.get_all_rows()[1:]

            imprimer "lignes1 :", lignes1

            test_data_pass_flag=Représentation True#Result, utilisée pour l'écriture finale des résultats Excel

            pour id1,ligne dans enumerate(rows1):

                si row[7].value == 'y' :

                    essayer:

                        #print row[1].value,row[2].value,row[3].value,row[4].value,row[5].value

                        imprimer "log0711", ligne [1], ligne [1].value

                        imprimer "log0711", type (ligne [1]. valeur)

                        #Effectuer l'opération réelle d'ajout de contacts

                        add_contact (pilote, ligne [1]. valeur, ligne [2]. valeur, ligne [3]. valeur, ligne [4]. valeur, ligne [5]. valeur)

                        print "assert word:",row[6].value

                        affirmer la ligne [6] .value dans driver.page_source

                        pe.write_cell_content(id1+2,10,"pass")#assert ne signale pas d'erreur, indiquant que l'assertion est réussie

                    sauf exception,e :

                        #print u"Message d'exception 01",e.message

                        pe.write_cell_content(id1+2,10,"échec")

                        test_data_pass_flag=False#Le code atteint ce point, indiquant qu'il y a une exception et que le test a échoué.

                        info(u"Message d'exception 01" + e.message) #Journal de sortie

                else:#L'identifiant de la description est 'n', ignorez les données

                    pe.write_cell_content(id1+2,10,u"忽略")

                    continuer

            if test_data_pass_flag ==True:#Si le flag est True, le résultat est réussi

                pe.set_sheet_by_name(u"Compte 126")

                pe.write_cell_content(id+2,5,"成功")

            else:#Indique que l'indicateur est False

                pe.set_sheet_by_name(u"Compte 126")

                pe.write_cell_content(id+2,5,"Échec")

        sauf exception,e :

            pe.set_sheet_by_name(u"Compte 126")

            #print u"Message d'exception 02:",e

            pe.write_cell_content(id+2,6,"échec")

            info(u"Message d'exception 02 :"+e.message)#Journal de sortie

        temps.sommeil(2)

        pilote.quit()

    else:#Prendre cette branche, indiquant que l'identifiant est "n"

        pe.set_sheet_by_name(u"Compte 126")

        pe.write_cell_content(id+2,6,u"忽略")

        continuer

Résultat : Exécuter OK

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/TestScript/TestScript.py

126compte

xiaxiaoxu1987 route de la gloire

2018-07-11 22:55:25 log.py[line:19] INFO connexion réussie

Personne de contact

lignes 1 : [(<Cellule u'\u8054\u7cfb\u4eba'.A2>, <Cellule u'\u8054\u7cfb\u4eba'.B2>, <Cellule u'\u8054\u7cfb\u4eba'.C2>, < Cellule u'\u8054\u7cfb\u4eba'.D2>, <Cellule u'\u8054\u7cfb\u4eba'.E2>, <Cellule u'\u8054\u7cfb\u4eba'.F2>, <Cellule u'\u8054 \u7cfb\u4eba'.G2>, <Cellule u'\u8054\u7cfb\u4eba'.H2>, <Cellule u'\u8054\u7cfb\u4eba'.I2>, <Cellule u'\u8054\u7cfb\u4eba' .J2>), (<Cellule u'\u8054\u7cfb\u4eba'.A3>, <Cellule u'\u8054\u7cfb\u4eba'.B3>, <Cellule u'\u8054\u7cfb\u4eba'.C3> , <Cellule u'\u8054\u7cfb\u4eba'.D3>, <Cellule u'\u8054\u7cfb\u4eba'.E3>, <Cellule u'\u8054\u7cfb\u4eba'.F3>, <Cellule u' \u8054\u7cfb\u4eba'.G3>, <Cellule u'\u8054\u7cfb\u4eba'.H3>,<Cellule u'\u8054\u7cfb\u4eba'.I3>, <Cellule u'\u8054\u7cfb\u4eba'.J3>), (<Cellule u'\u8054\u7cfb\u4eba'.A4>, <Cellule u'\u8054\u7cfb\u4eba'.A4> '\u8054\u7cfb\u4eba'.B4>, <Cellule u'\u8054\u7cfb\u4eba'.C4>, <Cellule u'\u8054\u7cfb\u4eba'.D4>, <Cellule u'\u8054\u7cfb \u4eba'.E4>, <Cellule u'\u8054\u7cfb\u4eba'.F4>, <Cellule u'\u8054\u7cfb\u4eba'.G4>, <Cellule u'\u8054\u7cfb\u4eba'.H4 >, <Cellule u'\u8054\u7cfb\u4eba'.I4>, <Cellule u'\u8054\u7cfb\u4eba'.J4>, (<Cellule u'\u8054\u7cfb\u4eba'.A5>, < Cellule u'\u8054\u7cfb\u4eba'.B5>, <Cellule u'\u8054\u7cfb\u4eba'.C5>, <Cellule u'\u8054\u7cfb\u4eba'.D5>, <Cellule u'\u8054 \u7cfb\u4eba'.E5>, <Cellule u'\u8054\u7cfb\u4eba'.F5>,<Cellule u'\u8054\u7cfb\u4eba'.G5>, <Cellule u'\u8054\u7cfb\u4eba'.H5>, <Cellule u'\u8054\u7cfb\u4eba'.I5>, <Cellule u'\ u8054\u7cfb\u4eba'.J5>)]

log0711 <Cell u'\u8054\u7cfb\u4eba'.B2> lily

log0711 <type 'unicode'>

assert word: [email protected]

Process finished with exit code 0

login.py文件里也可以在执行登录动作后打个日志,提示登录成功。

至此,主程序中实现了读取数据、登录邮箱、添加联系人、往excel里写入测试结果,基本的功能已经搞定了,下面再搞一个地方,就接近完美了,就是对时间的封装,在程序中调用时间函数写入指定的时间格式。

步骤13—常用时间操作的封装
在Util包下新建FormatTime.py
FormatTime.py

#encoding=utf-8

#author-夏晓旭

#encoding=utf-8

import time

from datetime import timedelta,date

def date_time_chinese():

    print u"returns the current time string,format for YYYY年mm月dd日HH时MM分SS秒"

    return time.strftime("%Y年%m月%d日 %H时%M分%S秒",time.localtime())

def date_chinese():

    print u"returns the current time string, format for YYYY年mm月dd日"

    return time.strftime("%Y年%m月%d日",time.localtime())

def time_chinese():

    print u"returns the current time string,format for HH时 MM分 SS秒"

    return time.strftime("%H heure %M minute %S seconde", time.localtime())

def date_time() :

    print "renvoie la chaîne d'heure actuelle, au format AAAA-mm-jj HH:MM:SS"

    return time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())

def date_time_slash() :

    print "renvoie la chaîne d'heure actuelle, au format AAAA/mm/jj HH:MM:SS"

    return time.strftime("%Y/%m/%d %H:%M:%S",time.localtime())

dates par défaut() :

    print "renvoie la chaîne d'heure actuelle, au format AAAA-mm-jj"

    return time.strftime("%Y-%m-%d",time.localtime())

def date_slash() :

    print "renvoie la chaîne d'heure actuelle, au format AAAA/mm/jj"

    return time.strftime("%Y/%m/%d",time.localtime())

def fois() :

    print "renvoie la chaîne d'heure actuelle, au format HH:MM:SS"

    return time.strftime("%H:%M:%S",time.localtime())

année par défaut() :

    print "renvoie la chaîne d'heure actuelle, le format pour l'année"

    retourner time.strftime("%Y",time.localtime())

mois par défaut() :

    print "renvoie la chaîne d'heure actuelle, le format du mois"

    retourner time.strftime("%m",time.localtime())

jour def() :

    print "renvoie la chaîne d'heure actuelle, le format du jour"

    return time.strftime("%d",time.localtime())

heure par défaut() :

    print "renvoie la chaîne d'heure actuelle, au format Heure"

    retourner time.strftime("%H",time.localtime())

def minute() :

    print "renvoie la chaîne de l'heure actuelle, au format minute"

    retourner time.strftime("%M",time.localtime())

def secondes() :

    print "renvoie la chaîne d'heure actuelle, formate en secondes"

    retourner time.strftime("%S",time.localtime())

def str_to_tuple(stime) :

    print "renvoie la variable chaîne dans des tuples temporels"

    return time.strptime(stime,"%Y-%m-%d %H:%M:%S")

def add_date(jour_num):

    aujourd'hui=date.aujourd'hui()

    print "renvoie la date actuelle-%s et un intervalle de temps-%s" %(today,day_num)

    times=aujourd'hui+timedelta(days=day_num)

    heures de retour

def sub_date(jour_num) :

    aujourd'hui=date.aujourd'hui()

    print "renvoie la date actuelle-%s moins un intervalle de temps-%s" %(today,day_num)

    times=aujourd'hui-timedelta(days=day_num)

    heures de retour

si __name__=='__main__' :

    #Tester le code

    imprimer date_time_chinese()

    imprimer date_chinese()

    imprimer time_chinese()

    imprimer date_heure()

    imprimer date_time_slash()

    imprimer les dates()

    imprimer date_slash()

    temps d'impression()

    année d'impression()

    imprimer le mois()

    jour d'impression()

    heure d'impression()

    imprimer la minute()

    imprimer les secondes()

    time1=time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())

    imprimer str_to_tuple (time1)

    imprimer add_date(2)

    imprimer sous_date(2)

Résultat : ok, le chinois n'a pas besoin d'être transcodé dans pycharm, mais le transcodage est nécessaire pour s'exécuter dans le bloc-notes.

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/Util/FormatTime.py

renvoie la chaîne d'heure actuelle, au format AAAA année mm mois jj jour HH heure MM minute SS seconde

11 juillet 2018 23:01:36

renvoie la chaîne de l'heure actuelle, au format AAAA mm mois jj jour

11 juillet 2018

renvoie la chaîne d'heure actuelle, au format HH heures MM minutes SS secondes

23:01:36

renvoie la chaîne de l'heure actuelle, au format AAAA-mm-jj HH:MM:SS

2018-07-11 23:01:36

renvoie la chaîne de l'heure actuelle, au format AAAA/mm/jj HH:MM:SS

2018/07/11 23:01:36

renvoie la chaîne de l'heure actuelle, au format AAAA-mm-jj

2018-07-11

renvoie la chaîne de l'heure actuelle, au format AAAA/mm/jj

2018/07/11

renvoie la chaîne de l'heure actuelle, au format HH:MM:SS

23:01:36

renvoie la chaîne d'heure actuelle, le format de l'année

2018

renvoie la chaîne d'heure actuelle, le format du mois

07

renvoie la chaîne de l'heure actuelle, le format du jour

11

renvoie la chaîne d'heure actuelle, au format Heure

23

renvoie la chaîne de l'heure actuelle, au format minute

01

renvoie la chaîne de l'heure actuelle, formate en secondes

36

renvoie la variable chaîne dans des tuples temporels

time.struct_time(tm_year=2018, tm_mon=7, tm_mday=11, tm_hour=23, tm_min=1, tm_sec=36, tm_wday=2, tm_yday=192, tm_isdst=-1)

renvoie la date actuelle-2018-07-11 et un intervalle de temps-2

2018-07-13

renvoie la date actuelle-2018-07-11 moins un intervalle de temps-2

2018-07-09

Processus terminé avec le code de sortie 0

Modifiez le programme principal, appelez la fonction heure et imprimez l'heure
TestScript.py :

#encodage=utf-8

#auteur-Xia Xiaoxu

à partir du pilote Web d'importation de sélénium

heure d'importation

à partir de selenium.webdriver.support.ui importer WebDriverWait

à partir de selenium.webdriver.common.by import Par

à partir de selenium.common.exceptions importer TimeoutException, NoSuchElementException

traçage des importations

à partir de l'importation PageObject.Login_Page *

à partir de l'importation PageObject.AddressBook *

depuis l'importation Action.add_contact *

à partir de l'importation Action.login *

à partir de l'importation ProjectVar.var *

à partir de l'importation Util.Excel *

à partir de l'importation Util.log *

à partir de l'importation Util.FormatTime *

driver=webdriver.Firefox(executable_path='c:\\geckodriver')

driver.get('http://mail.126.com')

pe=parseExcel(test_data_excel_path)

pe.set_sheet_by_name(u"Compte 126")

imprimer pe.get_default_sheet()

lignes=pe.get_all_rows()[1:]

pour l'identifiant, ligne dans enumerate (lignes):

    si ligne[4].value =='y' :

        nom d'utilisateur = ligne[1].value

        mot de passe = ligne[2].value

        imprimer le nom d'utilisateur, le mot de passe

        essayer:

            login (pilote, nom d'utilisateur, mot de passe)

            pe.set_sheet_by_name(u"Contact")

            imprimer pe.get_default_sheet()

            rows1=pe.get_all_rows()[1:]

            imprimer "lignes1 :", lignes1

            test_data_pass_flag=Représentation True#Result, utilisée pour l'écriture finale des résultats Excel

            pour id1,ligne dans enumerate(rows1):

                si row[7].value == 'y' :

                    essayer:

                        #print row[1].value,row[2].value,row[3].value,row[4].value,row[5].value

                        imprimer "log0711", ligne [1], ligne [1].value

                        imprimer "log0711", type (ligne [1]. valeur)

                        #Effectuer l'opération réelle d'ajout de contacts

                        add_contact (pilote, ligne [1]. valeur, ligne [2]. valeur, ligne [3]. valeur, ligne [4]. valeur, ligne [5]. valeur)

                        pe.write_cell_content(id1 + 2, 9, date_time())

                        print "assert word:",row[6].value

                        affirmer la ligne [6] .value dans driver.page_source

                        pe.write_cell_content(id1+2,10,"pass")#assert ne signale pas d'erreur, indiquant que l'assertion est réussie

                    sauf exception,e :

                        #print u"Message d'exception 01",e.message

                        pe.write_cell_content(id1+2,10,"échec")

                        pe.write_cell_content(id1+2,9,date_time())

                        test_data_pass_flag=False#Le code atteint ce point, indiquant qu'il y a une exception et que le test a échoué.

                        info(u"Message d'exception 01" + e.message) # Journal de sortie

                else:#L'identifiant de la description est 'n', ignorez les données

                    pe.write_cell_content(id1+2,10,u"忽略")

                    pe.write_cell_content(id1 + 2, 9,date_time())

                    continuer

            if test_data_pass_flag ==True:#Si le flag est True, le résultat est réussi

                pe.set_sheet_by_name(u"Compte 126")

                pe.write_cell_content(id+2,6,"成功")

            else:#Indique que l'indicateur est False

                pe.set_sheet_by_name(u"Compte 126")

                pe.write_cell_content(id+2,6,"Échec")

        sauf exception,e :

            pe.set_sheet_by_name(u"Compte 126")

            #print u"Message d'exception 02:",e

            pe.write_cell_content(id+2,6,"échec")

            info(u"Message d'exception 02 :"+e.message)#Journal de sortie

        temps.sommeil(2)

        pilote.quit()

    else:#Prendre cette branche, indiquant que l'identifiant est "n"

        pe.set_sheet_by_name(u"Compte 126")

        pe.write_cell_content(id+2,6,u"忽略")

        continuer

Résultat : OK

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/TestScript/TestScript.py

126compte

xiaxiaoxu1987 route de la gloire

2018-07-11 23:17:39 log.py[line:19] INFO connexion réussie

Personne de contact

lignes 1 : [(<Cellule u'\u8054\u7cfb\u4eba'.A2>, <Cellule u'\u8054\u7cfb\u4eba'.B2>, <Cellule u'\u8054\u7cfb\u4eba'.C2>, < Cellule u'\u8054\u7cfb\u4eba'.D2>, <Cellule u'\u8054\u7cfb\u4eba'.E2>, <Cellule u'\u8054\u7cfb\u4eba'.F2>, <Cellule u'\u8054 \u7cfb\u4eba'.G2>, <Cellule u'\u8054\u7cfb\u4eba'.H2>, <Cellule u'\u8054\u7cfb\u4eba'.I2>, <Cellule u'\u8054\u7cfb\u4eba' .J2>), (<Cellule u'\u8054\u7cfb\u4eba'.A3>, <Cellule u'\u8054\u7cfb\u4eba'.B3>, <Cellule u'\u8054\u7cfb\u4eba'.C3> , <Cellule u'\u8054\u7cfb\u4eba'.D3>, <Cellule u'\u8054\u7cfb\u4eba'.E3>, <Cellule u'\u8054\u7cfb\u4eba'.F3>, <Cellule u' \u8054\u7cfb\u4eba'.G3>, <Cellule u'\u8054\u7cfb\u4eba'.H3>,<Cellule u'\u8054\u7cfb\u4eba'.I3>, <Cellule u'\u8054\u7cfb\u4eba'.J3>), (<Cellule u'\u8054\u7cfb\u4eba'.A4>, <Cellule u'\u8054\u7cfb\u4eba'.A4> '\u8054\u7cfb\u4eba'.B4>, <Cellule u'\u8054\u7cfb\u4eba'.C4>, <Cellule u'\u8054\u7cfb\u4eba'.D4>, <Cellule u'\u8054\u7cfb \u4eba'.E4>, <Cellule u'\u8054\u7cfb\u4eba'.F4>, <Cellule u'\u8054\u7cfb\u4eba'.G4>, <Cellule u'\u8054\u7cfb\u4eba'.H4 >, <Cellule u'\u8054\u7cfb\u4eba'.I4>, <Cellule u'\u8054\u7cfb\u4eba'.J4>, (<Cellule u'\u8054\u7cfb\u4eba'.A5>, < Cellule u'\u8054\u7cfb\u4eba'.B5>, <Cellule u'\u8054\u7cfb\u4eba'.C5>, <Cellule u'\u8054\u7cfb\u4eba'.D5>, <Cellule u'\u8054 \u7cfb\u4eba'.E5>, <Cellule u'\u8054\u7cfb\u4eba'.F5>,<Cellule u'\u8054\u7cfb\u4eba'.G5>, <Cellule u'\u8054\u7cfb\u4eba'.H5>, <Cellule u'\u8054\u7cfb\u4eba'.I5>, <Cellule u'\ u8054\u7cfb\u4eba'.J5>)]

log0711 <Cellule u'\u8054\u7cfb\u4eba'.B2> lily

log0711 <type 'unicode'>

renvoie la chaîne de l'heure actuelle, au format AAAA-mm-jj HH:MM:SS

affirmer le mot : [email protected]

renvoie la chaîne de l'heure actuelle, au format AAAA-mm-jj HH:MM:SS

renvoie la chaîne de l'heure actuelle, au format AAAA-mm-jj HH:MM:SS

renvoie la chaîne de l'heure actuelle, au format AAAA-mm-jj HH:MM:SS

Processus terminé avec le code de sortie 0

Excel écrit les résultats :

Résumer:

Maintenant, nous commençons par assembler des fonctions dispersées pour implémenter une fonction plus grande, puis organisons la fonction plus grande en une fonction plus grande. En fin de compte, ce que nous voyons dans le programme principal est la combinaison de grandes fonctions indépendantes. Voir Cela a l'air soigné, simple, très lisible et facile à entretenir.

De cette façon, nous transformons l'ensemble du cadre d'une liste dispersée de codes en encapsulant des fonctions en morceaux. Nous séparons les données et les programmes, encapsulons et intégrons une certaine fonction indépendante. Dans ce processus, nous nous familiarisons avec les étapes de construction d'un cadre. Après avoir connu les tenants et aboutissants et les avantages de l'encapsuler dans plusieurs gros blocs, lorsque vous construirez le framework de test plus tard, vous pourrez simplement suivre ces gros blocs. Il sera relativement plus facile d'accepter cette idée, cette logique et sa nécessité. comprendre pourquoi un tel cadre de test devrait être construit et les principes de ce cadre de test, puis tirer des conclusions et l'étendre à d'autres types de cadres de test.

Plus de pratique pratique ~

Voici la structure du cadre basé sur les données :

Structure du cadre basée sur les données :
Action :
    fonction encapsulée des éléments opérationnels, tels que la connexion et l'ajout de contacts. . .

conf :
Fichier de configuration du journal Fichier
de configuration des éléments de positionnement Fichier
de configuration de la base de données
    
PageObject :
    Une page est une classe, et la méthode de la classe peut obtenir des éléments associés sur la page

ProjectVar :
Chemin
du projet Variables globales liées au projet
TestData : (fichier ou Excel)
test
données de test de cas

TestScript :
Le programme principal qui exécute le framework de test : l'entrée, qui lit principalement les fichiers de données de test
                      et enregistre les résultats des tests.

Fonction de classe Util-Tool
 :
      Lire le fichier de configuration,
      classe d'outils Excel           , méthode
      de classe temporelle pour trouver des éléments, méthode           pour lire le fichier de configuration des éléments de positionnement,           méthode de journalisation           , modèle de rapport de capture           d'écran           d'opération de journalisation





Si vous avez besoin du code source du framework, vous pouvez laisser votre email dans la zone commentaire~


Enfin, je partagerai avec vous les documents et le matériel d'apprentissage que j'ai accumulés et véridiques. Si nécessaire, vous pouvez simplement les récupérer. Le contenu ci-dessus devrait être l'entrepôt de préparation le plus complet et le plus complet

pour les amis testeurs de logiciels. Afin de mieux Organisez-le Pour chaque module, j'ai également consulté de nombreux articles de blog et projets de haute qualité sur Internet, en essayant de ne manquer aucun point de connaissance. De nombreux amis se sont appuyés sur ces contenus pour les examiner et ont reçu des offres de grands fabricants tels que BATJ. a également beaucoup aidé. En tant qu'apprenant en tests de logiciels, j'espère que cela pourra également vous aider.

Suivez mon compte officiel WeChat ci-dessous pour l'obtenir gratuitement ! ↓ ↓ ↓ ↓ ↓

Je suppose que tu aimes

Origine blog.csdn.net/weixin_56331124/article/details/132840168
conseillé
Classement