整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          前端架構(gòu)師基于京東門戶編寫的7篇html、css實(shí)戰(zhàn)

          前端架構(gòu)師基于京東門戶編寫的7篇html、css實(shí)戰(zhàn),代碼免費(fèi)分享!

          情提示:以下代碼是我們邀請的前端架構(gòu)師基于京東門戶編寫的html、css代碼,現(xiàn)在免費(fèi)分享給大家,獲取的方式為:

          關(guān)注此頭條號“互聯(lián)網(wǎng)IT信息”——>私信發(fā)送 “京東html” ,即可得到源代碼的獲取方式。

          家好,今天分享的是仿京東登錄頁面的簡單實(shí)現(xiàn)方法(結(jié)構(gòu)與樣式),首先我們依舊是先看下效果圖

          下面是HTML結(jié)構(gòu)

          下面是CSS樣式

          PS:本人也是小白一枚,自學(xué)沒幾天,疏漏之處在所難免,請多擔(dān)待!

          lask這個(gè)框架很輕量,做一些小工具還是可以很快上手的。

          1、自動(dòng)化

          某一天你入職了一家高大上的科技公司,開心的做著軟件測試的工作,每天點(diǎn)點(diǎn)點(diǎn),下班就走,晚上陪女朋友玩王者,生活很愜意。

          但是美好時(shí)光一般不長,這種生活很快被女主管打破。為了提升公司測試效率,公司決定引入自動(dòng)化流程,你在網(wǎng)上搜了一套技術(shù)方案 python + selenium,迅速寫了一套自動(dòng)化測試的腳本。

          from selenium import webdriver
          def test_selenium():
              driver=webdriver.Firefox()
              driver.get("http://www.baidu.com")
              ...
              driver.quit()
          ...
          

          編寫腳本的日子很累,你需要每天加班,而且沒有加班工資。 雖然如此,你也沒有太多怨言,因?yàn)槟隳苊黠@感覺到自己一點(diǎn)點(diǎn)掌握了自動(dòng)化測試的流程,正在踏入職業(yè)發(fā)展的新階段。這套腳本很快用于公司的主流程測試,也會(huì)在回歸測試中使用。

          因?yàn)榇罅康闹貜?fù)勞動(dòng)都可以用這套自動(dòng)化測試腳本代替,于是你又有時(shí)間陪女朋友了,上班也可以偶爾劃水了,也可以時(shí)不時(shí)瞄一瞄自己的基金有沒有漲。

          當(dāng)然,美好時(shí)光一般不長。在一次大改版中,前端頁面發(fā)生了大量變化,你的自動(dòng)化測試代碼因?yàn)闆]有做抽象封裝,基本已經(jīng)不能用了。

          又可以加班了,生活又可以充實(shí)起來了。你動(dòng)用了一些像 PageObject 的模式對代碼進(jìn)行了重新設(shè)計(jì),也加入了關(guān)鍵字驅(qū)動(dòng),盡量讓測試邏輯變成可配置的。 設(shè)計(jì)完成以后,當(dāng)前端頁面變化時(shí),只需要重點(diǎn)維護(hù)關(guān)鍵字表格。

          你又為公司做了一些貢獻(xiàn),你已經(jīng)完全勝任自動(dòng)化測試的工作,甚至能夠帶一兩個(gè)小弟。他們時(shí)不時(shí)找你問一些問題,但是對于自動(dòng)化的維護(hù)工作還是要靠你自己,當(dāng)你請假時(shí),這些工作只能停滯。于是公司希望你做一些改進(jìn),讓功能測試人員也可以運(yùn)行這些自動(dòng)化測試。

          2、開始測試平臺

          你看到網(wǎng)上有很多人提到測試平臺,想著自己也可以做一個(gè)可視化平臺,這樣功能測試人員也可以通過在界面上進(jìn)行簡單的設(shè)置,就可以使用底層的自動(dòng)化代碼了。很快 flask 出現(xiàn)在你的視線中,你做的第一個(gè)功能就是實(shí)現(xiàn)類似于 jenkins 的構(gòu)建功能。

          首先,你搭建了一個(gè) flask 服務(wù),服務(wù)啟動(dòng)后,你能順利訪問 5000 端口。

          from flask import Flask
          app=Flask(__name__)
          app.run(port=5000)
          

          然后,你配置了一個(gè) url 地址,當(dāng)訪問這個(gè) url 地址時(shí),服務(wù)會(huì)調(diào)用一個(gè)函數(shù),這個(gè) url 和函數(shù)的綁定關(guān)系就是路由。函數(shù)的返回值可以是普通字符串,可以是 json 數(shù)據(jù),也可以是 html 頁面。

          @app.route('/')
          def index():
              "show all projects in workspace dir"
              workspace=pathlib.Path(app.root_path) / 'workspace'
              projects=[project.name for project in workspace.iterdir()]
              return render_template('index.html', projects=projects)
          

          上面的代碼就是模仿 jenkins, 把自動(dòng)化測試的腳本放在項(xiàng)目的 workspace 目錄下,當(dāng)訪問 / 根路徑時(shí),index 函數(shù)就會(huì)被調(diào)用。index 函數(shù)的作用就是列舉 workspace 目錄下的所有項(xiàng)目名,通過 return 展示在前端界面。具體的前端代碼如下:

          <h2>展示所有的項(xiàng)目</h2>
          {% for p in projects %}
            <div>
              {{ p }} 
              <a href="/build?project={{p}}">構(gòu)建</a>
            </div>
          {% endfor %}
          

          在頁面上點(diǎn)擊構(gòu)建,程序會(huì)跳轉(zhuǎn)到 flask 設(shè)置好的 /build 這個(gè) url 中,這個(gè)路由負(fù)責(zé)運(yùn)行自動(dòng)化測試的代碼,他會(huì)接收用戶傳過來的 project 參數(shù),找到在 workspace 目錄下的項(xiàng)目,再執(zhí)行自動(dòng)化測試指令(這里統(tǒng)一用 pytest 指令)。

          @app.route("/build", methods=['get', 'post'])
          def build():
              project_name=request.args.get('project')
              pytest.main([f'workspace/{project_name}'])
              return "build success"
          

          到目前為止,完整的流程是這樣的:首先,在平臺首頁會(huì)展示所有可以構(gòu)建的項(xiàng)目,這些項(xiàng)目其實(shí)就是把 workspace 子目錄當(dāng)中的目錄名列舉出來;然后,點(diǎn)擊項(xiàng)目旁邊的構(gòu)建按鈕,跳轉(zhuǎn)到 /build,根據(jù)項(xiàng)目名稱執(zhí)行自動(dòng)化指令,等待自動(dòng)化任務(wù)執(zhí)行完成,返回 build success。

          3、優(yōu)化

          你基本上已經(jīng)實(shí)現(xiàn)了功能,現(xiàn)在功能測試人員可以通過你搭建的簡易平臺執(zhí)行自動(dòng)化命令。但是這個(gè)平臺還存在一些問題:第一、沒有收集到構(gòu)建信息,無法查看測試之后的結(jié)果;第二、用戶必須等待自行測試腳本執(zhí)行完成,才能返回前端具體的結(jié)果,如果自動(dòng)化測試的執(zhí)行時(shí)間很長,用戶會(huì)一直停在這個(gè)頁面,無法做其他事情。

          你想到了并發(fā)編程,創(chuàng)建一個(gè)子進(jìn)程單獨(dú)去運(yùn)行自動(dòng)化測試腳本,因?yàn)樽舆M(jìn)程可以和主進(jìn)程獨(dú)立,所以不需要等待子進(jìn)程執(zhí)行完成,主進(jìn)程就可以立即給前端返回結(jié)果。于是你重新編寫了 build 函數(shù):

          @app.route("/build")
          def build():
              id=uuid.uuid4().hex
              project_name=request.args.get('project')
              with open(id, mode='w', encoding='utf-8') as f:
                  subprocess.Popen(
                      ['pytest', f'workspace/{project_name}'],
                      stdout=f
                  )
              return redirect(f'/build-history/{id}')
          

          1、首先,通過 uuid 生成一個(gè) id 號來表示這一次構(gòu)建任務(wù),之后可以通過這個(gè) id 號查看此次構(gòu)建的記錄;

          2、通過 subprocess 創(chuàng)建子進(jìn)程運(yùn)行自動(dòng)化任務(wù),把輸出結(jié)果保存到文件當(dāng)中,文件名就是生成的 id 號,之后想查看構(gòu)建的結(jié)果時(shí),只需要讀取這個(gè)文件當(dāng)中的內(nèi)容;

          3、只要子進(jìn)程創(chuàng)建成功,馬上通過 redirect 重定向到查看結(jié)果的 url, 此時(shí)并不需要等到子進(jìn)程執(zhí)行完就可以查看構(gòu)建結(jié)果。

          查看構(gòu)建結(jié)果只需要通過 id 讀取文件中的內(nèi)容返回。

          @app.route("/build-history/<id>")
          def build_history(id):
              with open(id, encoding='utf-8') as f:
                  data=f.read()
              return data
          

          4、生成器

          上面讀取文件的代碼有點(diǎn)問題。當(dāng)構(gòu)建重定向到 /build-histrory 后,此時(shí)自動(dòng)化測試腳本才剛剛執(zhí)行,讀取文件中的內(nèi)容是空的。只有當(dāng)測試腳本運(yùn)行,產(chǎn)生越來越多的運(yùn)行記錄,文件中才會(huì)出現(xiàn)更多的內(nèi)容,你必須手動(dòng)刷新頁面才能獲取這些新內(nèi)容。 當(dāng)自動(dòng)化任務(wù)執(zhí)行時(shí)間很長的時(shí)候,你需要不停的刷新 /build-history 頁面才能獲取最新的構(gòu)建信息。直到子進(jìn)程結(jié)束,不再有新的內(nèi)容被寫入文件。

          為了動(dòng)態(tài)獲取文件數(shù)據(jù),你使用了生成器惰性獲取數(shù)據(jù),在 /build-history 的頁面加載過程中,只要運(yùn)行自動(dòng)化任務(wù)的子進(jìn)程還在運(yùn)行,就不停的讀取文件內(nèi)容,將它們動(dòng)態(tài)的返回給前端頁面。

          為了判斷子進(jìn)程的狀態(tài),在 /build 的時(shí)候,把子進(jìn)程的 pid 傳給 /build-history。

          @app.route("/build", methods=['get', 'post'])
          def build():
              id=uuid.uuid4().hex
              project_name=request.args.get('project')
              with open(id, mode='w', encoding='utf-8') as f:
                  proc=subprocess.Popen(
                      ['pytest', f'workspace/{project_name}'],
                      stdout=f
                  )
              return redirect(f'/build-history/{id}?pid={proc.pid}')
          

          在查看結(jié)果時(shí),先編寫一個(gè)生成器 stream, 每次讀取文件中 100 長度的數(shù)據(jù),直到進(jìn)程運(yùn)行結(jié)束。除了通過構(gòu)建后的重定向,你也可以手動(dòng)輸入 id,查看歷史構(gòu)建記錄。此時(shí)只需傳 id, 不需要傳進(jìn)程名,直接讀取文件中的數(shù)據(jù)。就算文件特別大,也可以通過批量加載,不至于因?yàn)橥瑫r(shí)讀取大量數(shù)據(jù)給服務(wù)器造成壓力。

          import psutil
          @app.route("/build-history/<id>")
          def build_history(id):
              pid=request.args.get('pid', None)
              def stream():
                  f=open(id, encoding='utf-8')
                  if not pid:
                      while True:
                          data=f.read(100)
                          if not data:
                              break
                          yield data
                  else:
                      try:
                          proc=psutil.Process(pid=int(pid))
                      except:
                          return 'no such pid'
                      else:
                          while proc.is_running():
                              data=f.read(100)
                              yield data
              return Response(stream())
          

          最后效果:

          5、總結(jié)

          一般來說,做自動(dòng)化測試只需要做到第一步,有腳本可以執(zhí)行,就可以代替重復(fù)勞動(dòng)。做測試平臺只是讓腳本變得更加好用。

          但是有很多的測試平臺讓自動(dòng)化運(yùn)行起來更加復(fù)雜,要配置很多很多參數(shù)才能跑一個(gè)完整的測試用例,這似乎有點(diǎn)折本求末,也是很多人都在做的事情。

          本文通過 flask 程序?qū)崿F(xiàn)了一個(gè)最簡單的 toy jenkins,輔助理解像 jenkins 這樣的工具如何執(zhí)行任務(wù)。其實(shí)像簡單的構(gòu)建任務(wù),做起來也有很多問題需要解決,這些只有在遇到具體業(yè)務(wù)的時(shí)候我們才會(huì)去思考。

          希望我們做的工具都是實(shí)用的,好用的。

          文章來自https://www.cnblogs.com/heniu/p/16565781.html


          主站蜘蛛池模板: 国模精品视频一区二区三区| 中文字幕av无码一区二区三区电影 | 在线精品亚洲一区二区小说| 国产免费播放一区二区| 国产A∨国片精品一区二区| 日本一道一区二区免费看| 性色AV 一区二区三区| 国产成人无码一区二区在线观看| 亚洲国产精品第一区二区三区| 国99精品无码一区二区三区| 国产福利一区二区三区| 日韩精品久久一区二区三区| 久久久久99人妻一区二区三区| 日韩精品电影一区亚洲| 国产丝袜视频一区二区三区| 亚拍精品一区二区三区| www.亚洲一区| 日韩一区二区a片免费观看| 亚洲爽爽一区二区三区| 冲田杏梨AV一区二区三区| 国内精品无码一区二区三区| 中文字幕日韩丝袜一区| 日韩视频免费一区二区三区| 日本一区二区不卡在线| 午夜天堂一区人妻| | 久久精品国产一区二区三区| 国产激情视频一区二区三区| 日韩免费无码一区二区视频| 中字幕一区二区三区乱码| 亚洲性日韩精品一区二区三区 | 无码人妻精品一区二区蜜桃网站| 精品国产免费一区二区| 丝袜无码一区二区三区| 精品久久一区二区| 日本在线观看一区二区三区| 一区二区亚洲精品精华液| 日韩一本之道一区中文字幕| 亚洲图片一区二区| 国产激情一区二区三区成人91| 国产成人精品第一区二区|