Cypress简易入门教程

01

Windows下安装

方法一

① 安装node.js(https://nodejs.org/en/download/),根据版本选择32位或64位。

② 确认ndejs 和npm是否安装上:

C:\Users\xiang>node -v

v12.18.0

C:\Users\xiang>npm-v

6.14.

③ 生成package.json(假设准备安装在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)

② 确认yarn是否安装上

C:\Users\xiang>yarn -v

1.22.4

③ 安装Cypress

C:\Users\xiang>cd c:\Cypress

C:\Cypress>yarnadd cypress --dev

02

运行

方法一

C:\Cypress\node_modules\.bin>cypress open

方法二

C:\Cypress>yarn run cypress open

方法三(我经常用的方法)

配置C:\Cypress\package.json

{

"license": "ISC",

"scripts": {

"cypress:open": "cypress open",

"cypress:run": "cypress run"

  },

"devDependencies": {

"cypress": "^4.8.0"

  }

}

打开运行控制器

C:\Cypress>yarn run cypress open

运行默认路径下的所有测试代码

C:\Cypress>yarn run cypress run

默认路径为C:\Cypress\cypress\integration,可以通过

{

  …

"integrationFolder": "cypress/integration/demo",

}

改变默认路径,上述代码中默认路径改为

C:\Cypress\cypress\integration\demo

03

测试框架&代码案例

before():

相当于unittest中的def setUp(cls)方法或者Junit的@Before方法标签;

after():

相当于unittest中的 def teardown(cls) 方法或者Junit的 @Before方法标签;

beforeEach() :

相当于unittest中的def setUpClass(cls) 方法或者Junit的@BeforeClass方法标签;

afterEach() :

相当于unittest中的def tearDownClass(cls) 方法或者Junit的@AfterClass方法标签。

GUI测试代码案例

1、第一个测试代码

测试电子商务系统登录程序

describe('login',function(){

const username = 'cindy'

const password = '123456'

context('测试电子商务网站',function(){

it('登录成功,调到商品列表页面',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','电子商务系统')

     })  

    })

})

2、元素查找 - get

<input type="text" class="s_ipt" name="wd" id="kw" maxlength="100" autocomplete="off">

根据元素 id 查找

cy.get('#kw')

根据元素名称查找

cy.get('input[name="wd"]')

根据元素的类名查找

cy.get('.s_ipt')

根据CSS selector查找、

cy.get('input[maxlength ="100"]')

3、元素查找 – contains

根据元素文本查找

cy.contains('value')  

根据元素属性及其文本查找

cy.get('div[name="ele-name"]').contains('value')

使用正则匹配元素文本以查找

cy.get('.class-name').contains(/[0-9]*/)

4、操作

type(String)、输入,比如

cy.get('#kw'). type('Testing')

click()、点击,比如

cy.get('.btn'). click ()

clear()、清空input或textarea的内容,比如

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()、如果某个元素不在当前可视范围,可以滑动至可视范围,比如

cy.get('#id').scrollIntoView()

scrollTo(String)、指定位置滑动,比如

cy.scrollTo('bottom')、cy.get('#id').scrollTo(250, 250)

5、鼠标操作

鼠标悬停事件:

cy.get('button').trigger('mouseover')

鼠标按下:

cy.get('button').trigger('mousedown')

鼠标抬起:

cy.get('button').trigger('mouseleave')

cy.get('button').trigger('mouseup')

鼠标长按事件:

cy.get('button').trigger('mousedown')

cy.wait(1000)

cy.get('button').trigger('mouseleave')

鼠标拖拽事件

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('测试百度网站',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('进入高级查询成功',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')

针对文本内容的断言

cy.get('a').parent('span.help').should('contain','click me')

针对元素可见与否的断言

cy.get('button').should('be.visible')

针对元素存在与否的断言

cy.get('#loading').should('not.exist')

针对元素状态的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('点击我的介绍成功',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, // 我们正在提交一份常规表格

body: {

username,

password,

csrfmiddlewaretoken:csrfToken // 将此作为主体的一部分插入

        }

      })

  })

  // csrf在返回的html中,我测试的Django产品的CSRF token用这种方法

it('策略#1:从HTML解析令牌', function(){

    // 如果我们不能改变我们的服务器代码以使解析CSRF令牌变得更容易,

    // 我们可以简单地使用cy.request来获取登录页面,然后解析HTML内容

    // 以找到嵌入在页面中的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在响应头中

it('策略#2:从响应头解析令牌',function(){

    // 如果我们将csrf令牌嵌入到响应头中,那么我们就可以更容易地提取它,

    // 而不必深究最终的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")

          })

      })

    })

   }) */

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352

推荐阅读更多精彩内容