網站首頁 編程語言 正文
cypress測試本地web應用
在之前的cypress介紹里曾提到過,cypress雖然也可以測試部署好的應用,但是它最大的能力還是發揮在測試本地應用上。
本章主要內容就是關于如何測試本地web應用的概述:
- cypress與后臺應用之間的關系。
- 如何配置cypress使其適合我們的應用
- 更好的繞過應用的身份驗證機制
一、啟動本地應用
在前面幾章內容中,代碼示例都是用的官方文檔的網頁進行測試的。那個環境相當于一個線上的生產環境,而且是cypress官方的,咱們除了正常訪問
啥也做不了。啟動本地應用就是啟動你自己開發的web應用,比如我本地的測試平臺的前端應用。
不過應該還會有小伙伴好奇,為什么就不能直接用線上已經部署好的,而非要用本地的?
這里,我概述一下官方的回答,以供參考:
- 在日常的本地開發中,cypress是圍繞著構建、優化的工具。
- 數據存根。
- 最重要的還是你要有控制這個應用的能力,比如,根據需要隨時更改調整應用的一些配置之類。
不過,也不是說線上環境和本地環境,你必須二選一才行,也可以都寫測試,這也是一個實用場景。比如,大多數的測試可以在本地環境跑,然后留一些
測試可以作為冒煙測試用,可以用到部署好的環境上去。
二、訪問本地應用
之前演示用的代碼用不上了,現在可以新建一個測試文件home_page_spec.js
。
describe('The Home Page', () => { it('successfully loads', () => { cy.visit('http://localhost:8010') // 這里換成你自己本地的url }) })
訪問成功。
三、配置Cypress
在Cypress項目中,其實有個配置文件cypress.json
,就在項目根目錄下,內容默認為空{}
。
在這里可以根據需要來添加cypress的各種配置,比如說 測試文件的位置、默認超時時間、環境變量、用哪個報告等等,這里暫時不展開了。
不過現在,可以在這里加一個baseUrl
的配置,因為后續訪問的路徑都是以這個url為基礎的。這樣就可以給cys.visit()
和cys .request()
這種命令
自動添加baseUrl前綴了。
{ "baseUrl": "http://localhost:8010" }
現在訪問一個相對路徑試下:
describe('The Home Page', () => { it('successfully loads', () => { cy.visit('/') }) })
訪問成功。
到這里,就可以開始寫你本地應用的測試了,至于怎么寫,就還是取決不同的項目需求了。
四、Seeding data
這里我理解為初始化數據,比如要測試一個頁面的登錄,可能就得向數據庫里插入一個用戶數據,方便使用。在之前用selenium的時候,
通常就在setup 和 teardown里來安排初始化測試數據的準備和清理。
在cypress中,也會有一些支持做這些額外拓展的事情的方法,通常是這3種:
cy.exec()
,可以執行系統命令。
cy.task()
,可以通過pluginsFile來在node中運行代碼。
cy.request()
,可以發送http請求。
比如下面這段代碼,演示的就是在測試執行之前,要做一系列事情來完成數據的初始化:
describe('The Home Page', () => { beforeEach(() => { // reset and seed the database prior to every test cy.exec('npm run db:reset && npm run db:seed') // seed a post in the DB that we control from our tests cy.request('POST', '/test/seed/post', { title: 'First Post', authorId: 1, body: '...', }) // seed a user in the DB that we can control from our tests cy.request('POST', '/test/seed/user', { name: 'Jane' }) .its('body') .as('currentUser') }) it('successfully loads', () => { // this.currentUser will now point to the response // body of the cy.request() that we could use // to log in or work with in some way cy.visit('/') }) })
這種用法其實本質上來說沒什么錯的,但實際上每個測試都要與服務器或者瀏覽器交互的,這難免會拖慢測試的效率。對于這個問題,cypress
提供了些更快更好的解決方案。
1. Stubbing the server
這里就是我理解的mock了,斷開與后端服務的依賴。既然我需要跟服務器交互才可以拿到需要的返回數據,如果能繞開交互,直接需要用啥數據就有啥數據,連后端應用都
不需要啟了,豈不美哉?關于stub內容很多,后續使用到再繼續分解。
2. 解決登錄問題
在以往編寫測試的過程中,登錄一直是一個比較大的問題。你只有登錄了,才可以進行后續的測試活動。那么如果我們把登錄抽離出去,然后每個測試執行之前都進行一次登錄操作,
理論上來講,也是可行的。
describe('The Login Page', () => { beforeEach(() => { // reset and seed the database prior to every test cy.exec('npm run db:reset && npm run db:seed') // seed a user in the DB that we can control from our tests // assuming it generates a random password for us cy.request('POST', '/test/seed/user', { username: 'jane.lane' }) .its('body') .as('currentUser') }) it('sets auth cookie when logging in via form submission', function () { // destructuring assignment of the this.currentUser object const { username, password } = this.currentUser cy.visit('/login') cy.get('input[name=username]').type(username) // {enter} causes the form to submit cy.get('input[name=password]').type(`${password}{enter}`) // we should be redirected to /dashboard cy.url().should('include', '/dashboard') // our auth cookie should be present cy.getCookie('your-session-cookie').should('exist') // UI should reflect this user being logged in cy.get('h1').should('contain', 'jane.lane') }) })
只不過這樣整個測試下來就變得非常的慢。所以,cypress呼吁不要在每次測試前使用UI登錄。
當然了,你正兒八經寫的測試代碼里肯定是測試UI的,但是如果這個測試涉及到其他前置的一些數據狀態的依賴,那么要避免通過UI去設置。
這里官方還舉了個購物車的例子加以說明。
假設要測試購物車的功能。要進行測試的話,得把產品添加到購物車中。那么產品從哪里來? 我是否要使用UI登錄到管理后臺,然后創建所有的產品,包括它們的描述、類別和圖片?
如果這樣做了,那是不是所有的產品我都要訪問一遍并且加到購物車里呢?
答案顯然是否定的,至于怎樣做最合適,還得到后續的學習中再分享。
繼續回到上面UI登錄的問題,因為cypress與selenium不同,在cypress中,可以通過使用cy.request()
來跳過使用UI的需要,cy.request()
可以自動獲取和設置cookie,完成登錄態的設置。那么上述的用UI執行登錄的代碼就可以優化成:
describe('The Dashboard Page', () => { beforeEach(() => { // reset and seed the database prior to every test cy.exec('npm run db:reset && npm run db:seed') // seed a user in the DB that we can control from our tests // assuming it generates a random password for us cy.request('POST', '/test/seed/user', { username: 'jane.lane' }) .its('body') .as('currentUser') }) it('logs in programmatically without using the UI', function () { // destructuring assignment of the this.currentUser object const { username, password } = this.currentUser // programmatically log us in without needing the UI cy.request('POST', '/login', { username, password, }) // now that we're logged in, we can visit // any kind of restricted route! cy.visit('/dashboard') // our auth cookie should be present cy.getCookie('your-session-cookie').should('exist') // UI should reflect this user being logged in cy.get('h1').should('contain', 'jane.lane') }) })
在官方看來,這個相比于selenium是一個大優點,其實我覺得也不盡然。這個優化思想是對的,不過在之前使用selenium的時候,雖然它內置的方法不支持這么做,但是可以借助
requests庫來迂回解決直接像后端發送請求的問題。
原文鏈接:https://blog.csdn.net/wessonlan/article/details/124813098
相關推薦
- 2023-07-24 前端常見狀態碼
- 2022-12-11 SQL中創建存儲過程_MsSql
- 2022-05-01 React的三大屬性你都知道嗎_React
- 2023-06-17 解讀C語言非void函數卻沒有return會怎么樣_C 語言
- 2022-04-04 asp.net使用原生控件實現自定義列導出功能的方法_實用技巧
- 2022-07-08 Asp.Net?Core7?preview4限流中間件新特性詳解_實用技巧
- 2022-01-21 Flink中window 窗口和時間以及watermark水印
- 2021-12-10 linux防火墻配置(基于yum倉的配置)詳細步驟_Linux
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支