01
Windows下安裝
方法一
① 安裝node.js(https://nodejs.org/en/download/),根據(jù)版本選擇32位或64位熟史。
② 確認(rèn)ndejs?和npm是否安裝上:
C:\Users\xiang>node -v
v12.18.0
C:\Users\xiang>npm-v
6.14.
③ 生成package.json(假設(shè)準(zhǔn)備安裝在c:\Cypress>)
C:\Users\xiang>cd c:\Cypress
C:\Cypress>npminit
④ 安裝Cypress
C:\Cypress>npm install cypress --save-dev
方法二
① 安裝yarn (https://yarnpkg.com/en/docs/install#windows-stable)
② 確認(rèn)yarn是否安裝上
C:\Users\xiang>yarn -v
1.22.4
③ 安裝Cypress
C:\Users\xiang>cd c:\Cypress
C:\Cypress>yarnadd cypress --dev
02
運(yùn)行
方法一
C:\Cypress\node_modules\.bin>cypress open
方法二
C:\Cypress>yarn run cypress open
方法三(我經(jīng)常用的方法)
配置C:\Cypress\package.json
{
"license": "ISC",
"scripts": {
"cypress:open": "cypress open",
"cypress:run": "cypress run"
? },
"devDependencies": {
"cypress": "^4.8.0"
? }
}
打開運(yùn)行控制器
C:\Cypress>yarn run cypress open
運(yùn)行默認(rèn)路徑下的所有測試代碼
C:\Cypress>yarn run cypress run
默認(rèn)路徑為C:\Cypress\cypress\integration焚鹊,可以通過
{
? …
"integrationFolder": "cypress/integration/demo",
…
}
改變默認(rèn)路徑,上述代碼中默認(rèn)路徑改為
C:\Cypress\cypress\integration\demo
03
測試框架&代碼案例
before():
相當(dāng)于unittest中的def setUp(cls)方法或者Junit的@Before方法標(biāo)簽;
after():
相當(dāng)于unittest中的?def teardown(cls)?方法或者Junit的 @Before方法標(biāo)簽譬正;
beforeEach()?:
相當(dāng)于unittest中的def setUpClass(cls)?方法或者Junit的@BeforeClass方法標(biāo)簽疫赎;
afterEach()?:
相當(dāng)于unittest中的def tearDownClass(cls)?方法或者Junit的@AfterClass方法標(biāo)簽盛撑。
GUI測試代碼案例
1、第一個測試代碼
測試電子商務(wù)系統(tǒng)登錄程序
describe('login',function(){
const username = 'cindy'
const password = '123456'
context('測試電子商務(wù)網(wǎng)站',function(){
it('登錄成功捧搞,調(diào)到商品列表頁面',function(){
cy.visit('http://127.0.0.1:8000')
cy.get('input[name=username]').type(username)
cy.get('input[name=password]').type(password)
? cy.get('form').submit()
? ? ? //斷言
cy.url().should('include','/goods_view')
? cy.get('title').should('contain','電子商務(wù)系統(tǒng)')
? ? ?})??
? ? })
})
2抵卫、元素查找 - get
<input type="text" class="s_ipt" name="wd" id="kw" maxlength="100" autocomplete="off">
根據(jù)元素 id?查找
cy.get('#kw')
根據(jù)元素名稱查找
cy.get('input[name="wd"]')
根據(jù)元素的類名查找
cy.get('.s_ipt')
根據(jù)CSS selector查找、
cy.get('input[maxlength ="100"]')
3胎撇、元素查找 – contains
根據(jù)元素文本查找
cy.contains('value')??
根據(jù)元素屬性及其文本查找
cy.get('div[name="ele-name"]').contains('value')
使用正則匹配元素文本以查找
cy.get('.class-name').contains(/[0-9]*/)
4介粘、操作
type(String)、輸入晚树,比如
cy.get('#kw'). type('Testing')
click()姻采、點(diǎn)擊,比如
cy.get('.btn'). click ()
clear()爵憎、清空input或textarea的內(nèi)容慨亲,比如
cy.get('.ant-input').clear()
submit()、提交表單纲堵,比如
cy.get('.ant-form').submit()
dblclick()巡雨、元素雙擊,比如
cy.get('.ant-btn').dblclick()
rightclick()席函、元素右擊铐望,比如
cy.get('.ant-btn').rightclick()
select(String)、對元素選擇,比如
cy.get('.ant-select').select('apples')
check()正蛙、勾選checkbox督弓,比如
cy.get('.ant-checkbox').check()
Uncheck、反選 checkbox乒验,比如
cy.get('.ant-checkbox').uncheck()
scrollIntoView()愚隧、如果某個元素不在當(dāng)前可視范圍,可以滑動至可視范圍锻全,比如
cy.get('#id').scrollIntoView()
scrollTo(String)狂塘、指定位置滑動,比如
cy.scrollTo('bottom')鳄厌、cy.get('#id').scrollTo(250, 250)
5荞胡、鼠標(biāo)操作
鼠標(biāo)懸停事件:
cy.get('button').trigger('mouseover')
鼠標(biāo)按下:
cy.get('button').trigger('mousedown')
鼠標(biāo)抬起:
cy.get('button').trigger('mouseleave')
cy.get('button').trigger('mouseup')
鼠標(biāo)長按事件:
cy.get('button').trigger('mousedown')
cy.wait(1000)
cy.get('button').trigger('mouseleave')
鼠標(biāo)拖拽事件
cy.get('[data-cy=draggable]')
.trigger('mousedown', {which:1,pageX:600,pageY:100})
.trigger('mousemove', {which:1,pageX:600,pageY:600 })
.trigger('mouseup')
describe('baidu',function(){
context('測試百度網(wǎng)站',function(){
it('查詢成功',function(){
? cy.visit('https://www.baidu.com')
cy.get('input[name=wd]').type("軟件測試")
cy.get('#su').click()
? cy.get('title').should('contain','百度搜索')
? ? ?})?
it('進(jìn)入高級查詢成功',function(){
cy.get('a[name=tj_settingicon]').trigger('mouseover')
cy.get('.bdpfmenu').should('exist')
? ? ?})??
? })
})
6、斷言
針對長度的斷言
cy.get('li.selected').should('have.length',3)
針對類的斷言
cy.get('from').fijd('input').should('not.have.class','disabled')
針對值斷言
cy.get('textarea').should('have.value','3testing')
針對文本內(nèi)容的斷言
cy.get('a').parent('span.help').should('contain','click me')
針對元素可見與否的斷言
cy.get('button').should('be.visible')
針對元素存在與否的斷言
cy.get('#loading').should('not.exist')
針對元素狀態(tài)的State的斷言
cy.get(':radio').should('be.checked')
針對CSS的斷言
cy.get('.completed').should('have.css','text-decoration','line-through')
7了嚎、跨iframe操作
describe('login',function(){
context('啄木鳥',function(){
it('點(diǎn)擊我的介紹成功',function(){
cy.visit('http://www.3testing.com')
cy.get('#head',{timeout: 2000})
.then($iframe=> {
cy.wrap($iframe.contents().find("#introduce"));
? ? ? ? ? ? })
? .then($btn =>{
? cy.wrap($btn).click()
? ? ? ? ? ? });
? ? ? //斷言
cy.url().should('include','introduce.html')
cy.get('title').should('contain','啄木鳥')
? ? ?})??
? })
})
8泪漂、多窗口操作
Cypress不支持多窗口操作。
04
API測試
1歪泳、普通API測試
describe('login',function(){
const username = 'cindy'
const password = '123456'
const producturl="http://127.0.0.1:8000/login_action/"
cy.request({
method: 'POST',
url:producturl,
body: {
username:username
password:password
}
? ? ? })
? })
2萝勤、CSRF token API測試
describe('login',function(){
const username = 'cindy'
const password = '123456'
const producturl="http://127.0.0.1:8000/login_action/"
Cypress.Commands.add('loginByCSRF', (csrfToken) => {
cy.request({
method: 'POST',
url:producturl,
failOnStatusCode:false, // 不要失敗,這樣我們才能斷言
form:true, // 我們正在提交一份常規(guī)表格
body: {
username,
password,
csrfmiddlewaretoken:csrfToken // 將此作為主體的一部分插入
? ? ? ? }
? ? ? })
? })
? // csrf在返回的html中,我測試的Django產(chǎn)品的CSRF token用這種方法
it('策略#1:從HTML解析令牌', function(){
? ? // 如果我們不能改變我們的服務(wù)器代碼以使解析CSRF令牌變得更容易呐伞,
? ? // 我們可以簡單地使用cy.request來獲取登錄頁面敌卓,然后解析HTML內(nèi)容
? ? // 以找到嵌入在頁面中的CSRF令牌
cy.request(producturl)
? .its('body')
? .then((body) => {
? ? ? ? //我們可以用Cypress.$解析字符串主體,從而使我們能夠輕松地查詢到它
cy.log(body)
const $html =Cypress.$(body)
const csrf? = $html.find("input[name=csrfmiddlewaretoken]").val()
cy.loginByCSRF(csrf)
.then((resp) => {
expect(resp.status).to.eq(200)
expect(resp.body).to.contain("Company 2017")
? ? ? ? ? })
? ? ? })
? ? })
? })
/*
? // 如果csrf在響應(yīng)頭中
it('策略#2:從響應(yīng)頭解析令牌',function(){
? ? // 如果我們將csrf令牌嵌入到響應(yīng)頭中荸哟,那么我們就可以更容易地提取它,
? ? // 而不必深究最終的HTML
cy.request(producturl)
.its('headers')
.then((headers) => {
const csrf =headers['csrftoken']
cy.log(csrf)
cy.loginByCSRF(csrf)
.then((resp) => {
expect(resp.status).to.eq(200)
expect(resp.body).to.contain("Company 2017")
? ? ? ? ? })
? ? ? })
? ? })
? ?}) */