<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Python+Selenium+Pytest+Allure+Jenkins實現(xiàn)的Web自動化框架

      一、測試的項目

      jpress-4.1.5 博客搭建平臺

      Linux服務(wù)器環(huán)境:JDK(1.8.0)+Tomcat(apache-tomcat-8.5.91)+MySql(8.0)

      準(zhǔn)備工作:將jpress-4.1.5.war 上傳到服務(wù)器,復(fù)制到 /usr/local/tomcat/webapps 目錄下,會自動解壓縮。

      訪問:http://服務(wù)器ip:端口/jpress-4.1.5/admin

      二、需求分析

      本項目要測試的是一個開源的Java項目,測試的功能包括:

      1. 用戶注冊
      2. 用戶登錄
      3. 后臺管理員登錄
      4. 添加文章
      5. 刪除文章

      本項目通過自動化測試的方法來驗證,用戶注冊、用戶登錄、管理員登錄、添加文章、信息的完整性、正確性。比如必填項、電子郵件的格式、密碼一致性、識別驗證碼。

      其中,識別驗證碼是本項目的難點,通過調(diào)用第三方接口實現(xiàn)。

      三、用例設(shè)計-部分用例舉例

      四、框架說明

      本框架是一套基于 Python+Selenium+Pytest+Allure+Jenkins 而設(shè)計的數(shù)據(jù)驅(qū)動Web自動化測試的框架。

      • 技術(shù)棧:Python、Pytest、Excel、Json、MySql、Allure、Jenkins。

      4.1 測試框架結(jié)構(gòu)圖如下:

      4.2 項目功能

      Python+Selenium+Pytest+Allure+Jenkins web自動化框架,使用Page Object設(shè)計模式,將頁面的元素和元素之間的操作方法進行分離。它有三層架構(gòu),分別為:基礎(chǔ)封裝層BasePage,PO頁面對象層,TestCase測試用例層。

      同時使用DDT數(shù)據(jù)驅(qū)動測試思想,將測試數(shù)據(jù)和測試用例分離,提高代碼復(fù)用率,減少重復(fù)代碼的編寫。

      該框架能夠結(jié)合 Pytest 進行單元測試,記錄日志,并生成 allure 測試報告,最后進行 Jenkins 集成項目實現(xiàn)集成部署,并發(fā)送測試報告郵件。

      五、代碼設(shè)計與功能說明

      5.1 POM簡介:Page Object Modle頁面對象模型

      1. 頁面對象模型(POM)是一種設(shè)計模式,用來管理維護一組web元素集的對象庫
      2. 在POM下,應(yīng)用程序的每一個頁面都有一個對應(yīng)的Page Class
      3. 每一個Page Class 維護著該web頁的元素集合、操作這些元素的方法
      4. Page Class中的方法命名最好根據(jù)對應(yīng)的業(yè)務(wù)場景進行

      中心思想:定位元素和測試用例分開,實現(xiàn)代碼松耦合的效果

      5.2 基礎(chǔ)封裝層:pages/basePage.py

      點擊查看代碼
      class BasePage(object):
          def __init__(self,driver):
              self.driver = driver
      
          def find_element(self,*loc):
              return self.driver.find_element(*loc)
      
          def type_text(self,text,*loc):
              self.find_element(*loc).send_keys(text)
      
          def click(self,*loc):
              self.find_element(*loc).click()
      
          def clear(self,*loc):
              self.find_element(*loc).clear()
      
          def get_title(self):
              return self.driver.title
      

      封裝查找元素、輸入測試數(shù)據(jù)、點擊、清空等常用操作方法。

      5.3 PO頁面對象層:pages/userLoginPage.py

      點擊查看代碼
      from time import sleep
      from selenium.webdriver.common.by import By
      from pages.basePage import BasePage
      
      class UserLoginPage(BasePage):
          username_input = (By.NAME,'user')
          pwd_input = (By.NAME,'pwd')
          captcha_input = (By.NAME, 'captcha')
          login_btn = (By.CLASS_NAME,'btn')
      
          def __init__(self,driver):
              BasePage.__init__(self,driver)
      
          def goto_login_page(self):
              self.driver.get('http://192.168.10.184:8072/jpress-4.1.5/user/login')
      
          def input_username(self,username):
              self.clear(*self.username_input)
              self.type_text(username,*self.username_input)
      
          def input_pwd(self,pwd):
              self.clear(*self.pwd_input)
              self.type_text(pwd, *self.pwd_input)
      
          def input_captcha(self,captcha):
              self.clear(*self.captcha_input)
              self.type_text(captcha,*self.captcha_input)
      
          def click_login_btn(self):
              self.click(*self.login_btn)
      

      pages/userLoginPage.py 維護了用戶登錄頁面的元素集合:用戶名、密碼、驗證碼、登錄按鈕;操作這些元素的方法:進入用戶登錄頁面、輸入用戶名、輸入密碼、輸入驗證碼、點擊登錄按鈕。

      5.4 TestCase測試用例層:testcases/testUserLogin.py

      點擊查看代碼
      # -*- coding: utf-8 -*-
      import pytest
      from selenium.webdriver.support.wait import WebDriverWait
      from pages.userLoginPage import UserLoginPage
      from selenium.webdriver.support import expected_conditions as EC
      from selenium import webdriver
      from time import sleep
      from util import util
      from selenium.webdriver.common.by import By
      
      class TestUserLogin(object):
          login_data=[
              ('','admin','這是必填內(nèi)容'),
              ('admin', '', '這是必填內(nèi)容'),
              ('admin', 'admin', '用戶中心')
          ]
      
          def setup_class(self):
              option = webdriver.ChromeOptions()
              # 無頭模式
              option.add_argument('headless')
              # 沙盒模式運行
              option.add_argument('no-sandbox')
              # 渲染時寫入/tmp
              option.add_argument('disable-dev-shm-usage')
              # 專門應(yīng)對無頭瀏覽器不能最大化屏幕的方案
              option.add_argument("--window-size=1920,1050")
      
              self.driver = webdriver.Chrome(options=option)
              self.loginPage = UserLoginPage(self.driver)
              self.loginPage.goto_login_page()
              self.logger = util.get_logger()
      
      
          # 測試用戶登錄
          @pytest.mark.parametrize('username,pwd,expected',login_data)
          def test_user_login_username(self,username,pwd,expected):
              # 輸入用戶名
              self.loginPage.input_username(username)
              # 輸入密碼
              self.loginPage.input_pwd(pwd)
              # 記錄日志
              self.logger.debug('輸入用戶名稱:%s,輸入的用戶密碼:%s',username,pwd)
      
              if username=='':
                  # 點擊登錄
                  self.loginPage.click_login_btn()
                  sleep(1)
                  try:
                      # assert self.driver.find_element_by_id('user-error').text == expected
                      assert self.driver.find_element(By.ID,'user-error').text == expected
                  except AssertionError as ae:
                      self.logger.error("報錯,報錯:%s", "用戶名為空登錄", exc_info=1)
              elif pwd == '':
                  # 點擊登錄
                  self.loginPage.click_login_btn()
                  sleep(1)
                  try:
                      # assert self.driver.find_element_by_id('pwd-error').text == expected
                      assert self.driver.find_element(By.ID,'pwd-error').text == expected
                  except AssertionError as ae:
                      self.logger.error("報錯,報錯:%s", "密碼為空登錄", exc_info=1)
              else:
                  # 自動識別驗證碼
                  captcha = util.get_code(self.driver, 'captcha-img')
                  # 輸入驗證碼
                  self.loginPage.input_captcha(captcha)
                  # 點擊登錄
                  self.loginPage.click_login_btn()
                  # 等待提示框
                  WebDriverWait(self.driver, 5).until(EC.title_is(expected))
                  sleep(1)
                  # 驗證
                  try:
                      assert self.driver.title == expected
                  except AssertionError as ae:
                      self.logger.error("報錯,報錯:%s", "登錄", exc_info=1)
      
      if __name__ == '__main__':
          pytest.main(['testUserLogin.py'])
      

      說明:

      1)使用chrome的headless無頭模式,是因為在Linux服務(wù)器上執(zhí)行該腳本時,服務(wù)器上的Chrome無GUI。

      2)使用了ddt的思想,將測試數(shù)據(jù)和測試腳本分離,且一套測試腳本可以執(zhí)行多組不同測試數(shù)據(jù)的用例。

      3)調(diào)用了日志模塊,將腳本運行過程日志及報錯日志,記錄到日志文件中,方便排查問題。

      5.5 工具類模塊:解決驗證碼識別、日志打印等問題

      點擊查看代碼
      
      import base64
      import json
      import os
      import pickle
      import random
      import string
      import time
      import requests
      from PIL import Image
      from selenium import webdriver
      from selenium.webdriver.common.by import By
      import logging.handlers
      import datetime
      
      _custom_url = "http://api.jfbym.com/api/YmServer/customApi"
      _token = "Z-lvHdVz4hyuYT8_SmrG53VDH7EW4req4mpkN1rQIeY"
      _headers = {
          'Content-Type': 'application/json'
      }
      
      
      def common_verify(image, verify_type="10110"):
          # 10110 通用數(shù)英1-4位
          payload = {
              "image": base64.b64encode(image).decode(),
              "token": _token,
              "type": verify_type
          }
          resp = requests.post(_custom_url, headers=_headers, data=json.dumps(payload))
          print(resp.text)
          return resp.json()['data']['data']
      
      # id 是要截圖的元素的id
      def save_img(driver,id):
          # 獲取驗證碼圖片
          t = time.time()
          path = os.path.dirname(os.path.dirname(__file__)) + '\\screenshots'
          picture_name1 = path + '\\' + str(t) + '.png'
      
          driver.save_screenshot(picture_name1)
          # ce = driver.find_element_by_id(id)  # id = captchaimg
          ce = driver.find_element(By.ID,id)
      
          left = ce.location['x']
          top = ce.location['y']
          right = ce.size['width'] + left
          height = ce.size['height'] + top
      
          im = Image.open(picture_name1)
          # 摳圖
          img = im.crop((left, top, right, height))
          t = time.time()
          picture_name2 = path + '\\' + str(t) + '.png'
          img.save(picture_name2)  # 把驗證碼的圖保存下來
          return picture_name2
      
      def get_code(driver,id):
          picture = save_img(driver,id)
          with open(picture, 'rb') as f:
              s = f.read()
          return common_verify(s)
      
      def gen_random_str():
          rand_str = ''.join(random.sample(string.ascii_letters + string.digits, 8))
          return rand_str
      
      def save_cookie(driver, path):
          with open(path, 'wb') as filehandler:
              cookies = driver.get_cookies()
              print(cookies)
              pickle.dump(cookies, filehandler)
      
      
      def load_cookie(driver, path):
          with open(path, 'rb') as cookiesfile:
              cookies = pickle.load(cookiesfile)
              for cookie in cookies:
                  driver.add_cookie(cookie)
      
      def get_logger():
          path = os.path.dirname(os.path.dirname(__file__)) + '\\logs\\'
          logger = logging.getLogger('mylogger')
          logger.setLevel(logging.DEBUG)
      
          rf_handler = logging.handlers.TimedRotatingFileHandler(path+'all.log',when='midnight',interval=1,backupCount=7,atTime=datetime.time(0,0,0,0))
          rf_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s"'))
          f_handler = logging.FileHandler(path+'error.log')
          f_handler.setLevel(logging.ERROR)
          f_handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(filename)s[:%(lineno)d] - %(message)s"))
      
          logger.addHandler(rf_handler)
          logger.addHandler(f_handler)
          return logger
      
      if __name__ == '__main__':
          driver = webdriver.Chrome()
          driver.get('http://192.168.10.184:8072/jpress-4.1.5/admin/login')
          id = "captcha-img"
          print(get_code(driver, id))
      

      5.6 主運行方法:runall.py

      點擊查看代碼
      # -*- coding: utf-8 -*-
      import pytest
      import os
      from testcases import *
      
      if __name__ == '__main__':
          #批量執(zhí)行文件夾下的測試用例
          pytest.main(['-s', '-v',
                       'testcases/testAdminLogin.py',
                       'testcases/testArticle.py',
                       'testcases/testUserLogin.py',
                       'testcases/testUserRegister.py',
                       '-q',
                       '--clean-alluredir',
                       '--alluredir', 'reports'])
          os.system("allure generate reports -c -o reports/allure_result/")
      

      總結(jié):

      1)批量執(zhí)行多個測試用例

      2)生成Allure測試報告,并將測試報告文件放到 reports/allure_result/路徑下

      六、GitLab管理代碼

      虛擬機的Linux發(fā)行版:

      前提條件:

      • 安裝Docker
      • 安裝Docker-compose

      6.1 安裝gitlab

      1)服務(wù)器中保證有docker、docker-compose

      $ docker version
      $ docker compose version
      

      2)訪問安全
      云服務(wù)器:設(shè)置安全組【阿里云服務(wù)器設(shè)置】
      虛擬機:關(guān)閉防火墻

      $ systemctl stop firewalld
      

      3)在/usr/local下創(chuàng)建/docker/ gitlab_docker目錄

      $ cd /usr/local
      $ sudo mkdir docker
      $ cd docker
      $ sudo mkdir gitlab_docker
      $ cd gitlab_docker/
      

      4)在/usr/local/docker/gitlab_docker下創(chuàng)建docker-compose.yml文件

      $ sudo vi docker-compose.yml
      

      用于編寫啟動docker的配置信息的文件
      配置文件內(nèi)容:

      external_url說明:

      • 虛擬機:虛擬機的ip;
      • 云服務(wù)器:服務(wù)器的公網(wǎng)ip

      5)重啟docker,啟動gitlab,會自動拉取鏡像

      $ sudo systemctl docker restart
      $ sudo docker compose up -d
      

      查看啟動日志:

      $ sudo docker logs –f gitlab
      

      6)進入gitlab容器內(nèi)部查看root密碼

      $ docker exec –it gitlab bash
      $ cat /etc/gitlab/initial_root_password
      
      該文件記錄了初始密碼(24h后刪除),登陸成功后修改密碼,如:
      Ki91HCFAUcp6Lg1iXCQsT+5M7aFzj6IFOjk16NIvj/I=
      

      2、登錄gitlab修改用戶密碼
      3、創(chuàng)建project,設(shè)置倉庫

      4、上傳管理代碼

      七、Jenkins持續(xù)集成

      7.1 安裝JDK

      版本:jdk-8u231-linux-x64.tar.gz

      $ sudo tar zxvf jdk-8u151-linux-x64.tar.gz -C /usr/local
      $ cd /usr/local
      $ sudo mv jdk1.8.0_151/ jdk/
      

      7.2 安裝Jenkins

      $ cd /usr/local
      $ mkdir docker
      $ cd docker
      $ mkdir jenkins_docker
      $ cd jenkins_docker/
      

      創(chuàng)建docker-compose.yml文件:

      重啟docker、啟動jenkins

      $ sudo systemctl restart docker
      啟動:
      $ sudo docker compose up –d
      查看日志是否啟動出現(xiàn)問題:
      $ sudo docker logs –f jenkins
      

      登錄Jenkins、安裝默認插件等。

      7.3 配置Jenkins

      1. 將 /usr/local下的jdk、maven挪到docker/jenkins_docker/data
      /usr/local/docker/jenkins_docker/data$ sudo mv /usr/local/jdk/ ./
      
      2. 指定容器卷下的jdk和jenkins
      容器內(nèi)的路徑:/var/jenkins_home/
      【系統(tǒng)管理-全局工具配置-JDK】
      jdk配置:/var/jenkins_home/jdk
      
      3.服務(wù)器配置/etc/profile文件:
      # jdk env
      export JAVA_HOME=/usr/local/docker/jenkins_docker/data/jdk
      export PATH=$PATH:$JAVA_HOME/bin
      
      4. 生效配置文件
      $ source /etc/profile
      

      7.4 Jenkins環(huán)境其他配置

      1)Jenkins 容器內(nèi)部安裝Python3,方便在構(gòu)建腳本中運行py文件

      2)Jenkins 容器內(nèi)部安裝 Chrome瀏覽器和對應(yīng)版本的chromedriver驅(qū)動

      7.5 創(chuàng)建SeleniumJpress任務(wù)并配置

      1)源碼管理:從gitlab拉取代碼

      2)構(gòu)建步驟:運行runall.py 腳本

      3)構(gòu)建后操作:Allure 報告的存放地址

      4)構(gòu)建后郵件通知:

      7.6 系統(tǒng)的配置補充

      1)環(huán)境變量:Jenkins容器中的環(huán)境變量

      2)郵件通知:注意密碼是授權(quán)碼

      3)SSH服務(wù)器配置

      4)JDK

      5)Aiiure Commandline

      八、構(gòu)建結(jié)果及報告查看

      控制臺輸出:

      Allure報告:

      posted @ 2023-12-29 18:07  hqq的進階日記  閱讀(3056)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 99re视频在线| 国产福利社区一区二区| 国产午夜福利不卡在线观看| 国模一区二区三区私拍视频 | 日本一本无道码日韩精品| 国产午夜福利免费入口| 欧洲美女黑人粗性暴交视频| 国产精品成人网址在线观看| 国产精品亚洲二区在线看| 内射干少妇亚洲69xxx| 久热这里只有精品视频3| 亚洲精品一区二区二三区| 福利网午夜视频一区二区| 福利一区二区视频在线| 人人人澡人人肉久久精品| 69天堂人成无码免费视频| 999精品色在线播放| 日韩无套无码精品| 亚洲午夜无码久久久久蜜臀av| 99久久精品国产一区二区暴力| 久久99精品九九九久久婷婷| 亚洲小说乱欧美另类| 国产精品久久久福利| 国产一区二区不卡在线视频 | 日韩人妻无码精品久久| 国产精品爽爽v在线观看无码| 亚洲无av在线中文字幕| 亚洲男女羞羞无遮挡久久丫| 色噜噜亚洲男人的天堂| 99久久无码一区人妻a黑| 欧洲性开放老太大| 大又大又粗又硬又爽少妇毛片| 国产高清在线不卡一区| 99福利一区二区视频| 伊人色综合一区二区三区| 无码精品一区二区免费AV| 内射老阿姨1区2区3区4区| 国产精品亚洲综合第一页| 国产在线永久视频| 国产老肥熟一区二区三区| 免费人成网站视频在线观看 |