Assertion in Cypress

In automated testing, assertion plays a vital role. The assertion is a condition that checks whether the program contains any bugs or not and to meet the client's specifications. The assertion is mainly used to detect the errors in the program.

Cypress bundles the popular Chai assertion library, as well as helpful extensions for Sinon and jQuery.

There are three styles in the chai library they are,

  • expect
  • should
  • assert

Assertions are further classified into two types based on the waiting mechanism, namely

  • Implicit assertion
  • Explicit assertion

Let us discuss it briefly with a simple example.

Example code: In the below code,

  • The First it block: Visiting the URL page.
  • The Second it block: To check whether the mentioned URL is correct or not.
    • cy.url() : This method gets the correct URL similar to the get() method, wherein the cy.get() method fetches the web element but in cy.url() fetches the web page URL.
    • The should is the assertion here, the test gets passed only if the URL contains a string named example.com in it.
describe(('My First Test suite'),
    function() {
        it('My First testcase',
            function() {
                cy.visit("https://example.com/");
            })
        it('should check correct url', () => {
            cy.url().should('include', 'example.com')
            //cy.url() gets the correct url
        })
    })

Output :

basic-program-assertion

Now in the above code, the URL is checked. Now let us alter the same program to check the web page element of the same web page.

Example code :

  • The Third it block: Checks the web page element is visible or not.
    • cy.get(): gets the web page element of h1
    • be.visible : confirms whether the web page element is visible or not
describe(('My First Test suite'),
    function() {
        it('My First testcase',
            function() {
                cy.visit("https://example.com/");
            })
        it('should check correct url', () => {
            cy.url().should('include', 'example.com')
            //cy.url() gets the correct url
        })
        it('should check for corect elements on the page', () => {
            cy.get('h1').should('be.visible')
            //cy.get() gets the web page element of h1
            //be.visible confirms whether the web page element is visible or not
        })
    })

Output :

assertion-continuation-program

The above program is successfully executed for the given web page element h1.

Now, let us change the CSS of the element from h1 to h5.

Code :

describe(('My First Test suite'),
    function() {
        it('My First testcase',
            function() {
                cy.visit("https://example.com/");
            })
        it('should check correct url', () => {
            cy.url().should('include', 'example.com')
            //cy.url() gets the correct url
        })
        it('should check for corect elements on the page', () => {
            cy.get('h5').should('be.visible')
            //cy.get() gets the web page element of h5
            //be.visible confirms whether the web page element is visible or not
        })
    })

Output: Error occurs because there is no web page element with CSS h5.

error-assertion-program

When the given web page element is wrong, the First and the second it blocks gets passed but the third it block gets failed. In the above program, the error occurs when the h1 is changed as h5 because no element contains CSS as h5.

Default built-in assertion in cypress

In testing, Assertion is the core concept. But in Cypress, you can use a few commands without using any assertion. This is because some commands have the default built-in assertion. The commands are,

Command Needs

cy.visit()

expect the page to send text/HTML content with a 200 status code.

cy.request()

expects the remote server to exist and provide a response.

cy.contains()

expects the element with content to eventually exist in the DOM[Document object model-API for HTML and XML Documents].

cy.get()

expects the element to eventually exist in the DOM.

.find()

expects the element to eventually exist in the DOM.

.type()

expects the element to eventually be in a typeable state.

.click()

expects the element to eventually be in an actionable state.

.its()

expects to eventually find a property on the current subject.

Let us now learn about the chainable getters used in the assertion before getting into the implicit and explicit assertion.

Chainable getters in the Assertion

To improve the readability of the code while using multiple commands using assertion these chainable getters are used. These are used to connect two or more assertions. Below is the list of the chainable getters.

  • and
  • has
  • same
  • still
  • have
  • with
  • but
  • does
  • at
  • of
  • to
  • be
  • been
  • is
  • that
  • which

expect and should are chainable styles and assert is non-chainable.

Implicit Assertion in Cypress

In Implicit assertion, Commands like .should()and .and depends or chained always with the parent command. The implicit assertion is used to specify the current subject. Implicit assertions are used when you want to assert multiple commands with a single subject.

Example code :

describe(('My First Test suite'),
    function() {
        it('My First testcase',
            function() {
                cy.visit("https://example.com/");
            })
        it('should check correct url', () => {
            cy.url().should('include', 'example.com')
        })
        it('should check for corect elements on the page', () => {
            cy.get('a').should('be.visible').and('have.attr', 'href')
        })
    })

Here the .should() command is chained with the parent command .get(). Again .and is chained with the .should() .

Output :

implicit-assertion

In the explicit assertion, styles such as assert and expect are used to make the assertion about a specified subject. For the BDD assertion, expect is used and for the TDD assertion, assert is used. Let us understand what is TDD and BDD assertion.

TDD and BDD assertion in Cypress

Based on the Test development the assertion is classified for TDD[Test Driven Development] and BDD[Behavior Driven Development]. TDD and BDD are the development technique of the tests.

In the TDD technique, the test cases are created first and then the code is written according to the test cases. This technique tests the actual implementation of the program. TDD proceeds the test in a particular user-defined pattern and it does not care much on the output.

TDD consumes more time while developing a program but it is more reliable.

In Cypress, the TDD process assert. is used as an assertion command which is non-chainable. Below is the list of the assertion available for TDD using assert.

ASSERTION

EXAMPLE

.isOk(object, [message])

assert.isOk('everything', 'everything is ok')

.isNotOk(object, [message])

assert.isNotOk(false, 'this will pass')

.equal(actual, expected, [message])

assert.equal(3, 3, 'vals equal')

.notEqual(actual, expected, [message])

assert.notEqual(3, 4, 'vals not equal')

.strictEqual(actual, expected, [message])

assert.strictEqual(true, true, 'bools strict eq')

.notStrictEqual(actual, expected, [message])

assert.notStrictEqual(5, '5', 'not strict eq')

.deepEqual(actual, expected, [message])

assert.deepEqual({ id: '1' }, { id: '1' })

.notDeepEqual(actual, expected, [message])

assert.notDeepEqual({ id: '1' }, { id: '2' })

.isAbove(valueToCheck, valueToBeAbove, [message])

assert.isAbove(6, 1, '6 greater than 1')

.isAtLeast(valueToCheck, valueToBeAtLeast, [message])

assert.isAtLeast(5, 2, '5 gt or eq to 2')

.isBelow(valueToCheck, valueToBeBelow, [message])

assert.isBelow(3, 6, '3 strict lt 6')

.isAtMost(valueToCheck, valueToBeAtMost, [message])

assert.isAtMost(4, 4, '4 lt or eq to 4')

.isTrue(value, [message])

assert.isTrue(true, 'this val is true')

.isNotTrue(value, [message])

assert.isNotTrue('tests are no fun', 'val not true')

.isFalse(value, [message])

assert.isFalse(false, 'val is false')

.isNotFalse(value, [message])

assert.isNotFalse('tests are fun', 'val not false')

.isNull(value, [message])

assert.isNull(err, 'there was no error')

.isNotNull(value, [message])

assert.isNotNull('hello', 'is not null')

.isNaN(value, [message])

assert.isNaN(NaN, 'NaN is NaN')

.isNotNaN(value, [message])

assert.isNotNaN(5, '5 is not NaN')

.exists(value, [message])

assert.exists(5, '5 is not null or undefined')

.notExists(value, [message])

assert.notExists(null, 'val is null or undefined')

.isUndefined(value, [message])

assert.isUndefined(undefined, 'val is undefined')

.isDefined(value, [message])

assert.isDefined('hello', 'val has been defined')

.isFunction(value, [message])

assert.isFunction(x => x * x, 'val is func')

.isNotFunction(value, [message])

assert.isNotFunction(5, 'val not funct')

.isObject(value, [message])

assert.isObject({num: 5}, 'val is object')

.isNotObject(value, [message])

assert.isNotObject(3, 'val not object')

.isArray(value, [message])

assert.isArray(['unit', 'e2e'], 'val is array')

.isNotArray(value, [message])

assert.isNotArray('e2e', 'val not array')

.isString(value, [message])

assert.isString('e2e', 'val is string')

.isNotString(value, [message])

assert.isNotString(2, 'val not string')

.isNumber(value, [message])

assert.isNumber(2, 'val is number')

.isNotNumber(value, [message])

assert.isNotNumber('e2e', 'val not number')

.isFinite(value, [message])

assert.isFinite('e2e', 'val is finite')

.isBoolean(value, [message])

assert.isBoolean(true, 'val is bool')

.isNotBoolean(value, [message])

assert.isNotBoolean('true', 'val not bool')

.typeOf(value, name, [message])

assert.typeOf('e2e', 'string', 'val is string')

.notTypeOf(value, name, [message])

assert.notTypeOf('e2e', 'number', 'val not number')

BDD Assertion

BDD assertion is used to test the behavior of the application. The tests which are done using the BDD have certain conditions. Only if the condition passes, the testing will be executed. expect and should are the BDD assertions. BDD assertions are chainable. Below is the list of the chainers used in BDD.

CHAINER EXAMPLE

not

expect(name).to.not.equal('Jane')

deep

expect(obj).to.deep.equal({ name: 'Jane' })

nested

expect({a: {b: ['x', 'y']}}).to.have.nested.property('a.b[1]')
expect({a: {b: ['x', 'y']}}).to.nested.include({'a.b[1]': 'y'})

ordered

expect([1, 2]).to.have.ordered.members([1, 2]).but.not.have.ordered.members([2, 1])

any

expect(arr).to.have.any.keys('age')

all

expect(arr).to.have.all.keys('name', 'age')

a(type)
Aliases: an

expect('test').to.be.a('string')

include(value)
Aliases: contain, includes, contains

expect([1,2,3]).to.include(2)

ok

expect(undefined).to.not.be.ok

true

expect(true).to.be.true

false

expect(false).to.be.false

null

expect(null).to.be.null

undefined

expect(undefined).to.be.undefined

exist

expect(myVar).to.exist

empty

expect([]).to.be.empty

arguments
Aliases: Arguments

expect(arguments).to.be.arguments

equal(value)
Aliases: equals, eq

expect(42).to.equal(42)

deep.equal(value)

expect({ name: 'Jane' }).to.deep.equal({ name: 'Jane' })

eql(value)
Aliases: eqls

expect({ name: 'Jane' }).to.eql({ name: 'Jane' })

greaterThan(value)
Aliases: gt, above

expect(10).to.be.greaterThan(5)

least(value)
Aliases: gte

expect(10).to.be.at.least(10)

lessThan(value)
Aliases: lt, below

expect(5).to.be.lessThan(10)

most(value)
Aliases: lte

expect('test').to.have.length.of.at.most(4)

within(start, finish)

expect(7).to.be.within(5,10)

instanceOf(constructor)
Aliases: instanceof

expect([1, 2, 3]).to.be.instanceOf(Array)

property(name, [value])

expect(obj).to.have.property('name')

deep.property(name, [value])

expect(deepObj).to.have.deep.property('tests[1]', 'e2e')

ownProperty(name)
Aliases: haveOwnProperty, own.property

expect('test').to.have.ownProperty('length')

ownPropertyDescriptor(name)
Aliases: haveOwnPropertyDescriptor

expect({a: 1}).to.have.ownPropertyDescriptor('a')

lengthOf(value)

expect('test').to.have.lengthOf(3)

match(RegExp)
Aliases: matches

expect('testing').to.match(/^test/)

string(string)

expect('testing').to.have.string('test')

keys(key1, [key2], […])
Aliases: key

expect({ pass: 1, fail: 2 }).to.have.keys('pass', 'fail')

throw(constructor)
Aliases: throws, Throw

expect(fn).to.throw(Error)

respondTo(method)
Aliases: respondsTo

expect(obj).to.respondTo('getName')

itself

expect(Foo).itself.to.respondTo('bar')

satisfy(method)
Aliases: satisfies

expect(1).to.satisfy((num) => { return num > 0 })

closeTo(expected, delta)
Aliases: approximately

expect(1.5).to.be.closeTo(1, 0.5)

members(set)

expect([1, 2, 3]).to.include.members([3, 2])

oneOf(values)

expect(2).to.be.oneOf([1,2,3])

change(function)
Aliases: changes

expect(fn).to.change(obj, 'val')

increase(function)
Aliases: increases

expect(fn).to.increase(obj, 'val')

decrease(function)
Aliases: decreases

expect(fn).to.decrease(obj, 'val')

Common Assertions used in Cypress

Below there are few example codes of commonly used assertion which is used along with.should()

Length

// retry until we find 3 matching <li.selected>
cy.get('li.selected').should('have.length', 3)

Class

// retry until this input does not have class disabled
cy.get('form').find('input').should('not.have.class', 'disabled')

Value

// retry until this textarea has the correct value
cy.get('textarea').should('have.value', 'example')

Contain

// retry until this span does not contain 'click me'
cy.get('a').parent('span.help').should('not.contain', 'click me')

Visibility

// retry until this button is visible
cy.get('button').should('be.visible')

Existence

// retry until loading spinner no longer exists
cy.get('#loading').should('not.exist')

Status

// retry until our radio is checked
cy.get(':radio').should('be.checked')

CSS

// retry until .completed has matching css
cy.get('.completed').should('have.css', 'text-decoration', 'line-through')
// retry until .accordion css have display: none
cy.get('#accordion').should('not.have.css', 'display', 'none')

Now we know, how to chain the assertion with the parent commands. In the next article, we can learn about the commands which are mostly used in cypress for testing.

Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions