Introduction to

Automated Testing

in

Hi.

Sanjeev Yadav

Trainee Software Engineer

What is Testing?

Why Should you care?

Testing = Documentation

// Import your highly mysterious function
const mysteriousFunction = require("./app");

// when you write descriptive test, it serves as a documentation

test("I don't know what this function do", () => {
    // Setup
    const input = "This is a sentence";
    const expectedResult = ["This", "is", "a", "sentence"];

    //
    const result = mysteriousFunction(input);

    // Verify
    expect(result).toBe(expectedResult);

});

// Looks like, the mysteriousFunction takes string as an input
// and returns an array of words

and more...

Get an error if you break code

Save Time

Think about possible issues & bugs

Integrate into build workflow

More modular code

Improve your code

Different Kinds of Tests

Fully Isolated

(e.g. testing one function)

With Dependencies

(e.g. testing a function

that calls another function)

Full Flow

(e.g.  Validating a login

flow)

Unit Test
Integration Test
End-to-End Test

Write thousands

of these

Write a good

couple of these

Write a

few of these

Test Driven Development

(TDD)

Write test first, then logic

Jest.js

  • JavaScript Testing Framework
  • Developed by Facebook
  • Works with  React/Angular/Vue/Node/TypeScript/Babel
  • Fast
  • Function Mock
  • Code Coverage & Snapshots

Jest Globals

// Runs a function before any of the tests in this file run.
beforeAll(fn, timeout)

// Runs a function before each of the tests in this file runs.
beforeEach(fn, timeout)

// Runs a function after all the tests in this file have completed.
afterAll(fn, timeout)

// Runs a function after each one of the tests in this file completes.
afterEach(fn, timeout)

// All you need in a test file is the test method which runs a test. 
test(name, fn, timeout)

Ex.

test('sum of 2 + 2 is 5', () => {
  expect(add(2, 2)).toBe(4);
});

Jest Matchers

Jest uses matchers to let you test values in different ways

// tobe uses Object.is
// to match two values
.toBe()
// use toEqual to match objects
// & arrays
.toEqual()
expect(2).toBe(2) // Pass

expect(true).toBe(false) // Fail

expect(null).toBe(null) // Pass
const data = {one: 1};
 
data['two'] = 2;

// Pass
expect(data).toEqual({one: 1, two: 2});

Truthiness

test('null', () => {
  const n = null;
  expect(n).toBeNull();
  expect(n).toBeDefined();
  expect(n).not.toBeUndefined();
  expect(n).not.toBeTruthy();
  expect(n).toBeFalsy();
});

Numbers

test('two plus two', () => {
  const value = 2 + 2;
  expect(value).toBeGreaterThan(3);
  expect(value).toBeGreaterThanOrEqual(3.5);
  expect(value).toBeLessThan(5);
  expect(value).toBeLessThanOrEqual(4.5);
});
test('there is no I in team', () => {
  expect('team').not.toMatch(/I/);
});

Strings

And more...

.toContain()

.toBeFalsy()

.toHaveBeenCalled()

.toBeSexy()

// and many more...

Part 2

Embarrassing myself while

trying to Live Code! 

Example of Unit & Integration testing

(add 2 (subtract 4 3))
add(2, subtract(4,3));

Input

Output

Compiler

Lisp Syntax
C Syntax

Compiler

Input

Parsing

Transformation

Code Generation

output

(add 2 (subtract 4 3))

abstract syntax tree

modified abstract syntax tree

add(2, subtract(4, 3));

Parsing

Input

tokenizer()

parser()

(add 2 (subtract 4 3))
[
  { type: 'paren',  value: '('        },
  { type: 'name',   value: 'add'      },
  { type: 'number', value: '2'        },
  { type: 'paren',  value: '('        },
  { type: 'name',   value: 'subtract' },
  { type: 'number', value: '4'        },
  { type: 'number', value: '3'        },
  { type: 'paren',  value: ')'        },
  { type: 'paren',  value: ')'        },
];
{
  type: 'Program',
    body: [
      {
        type: 'CallExpression',
        name: 'add',
        params: [
          {
            type: 'NumberLiteral',
            value: '2'
          },
          {
            type: 'CallExpression',
            name: 'subtract',
            params: [
              {
                type: 'NumberLiteral',
                value: '4'
              },
              {
                type: 'NumberLiteral',
                value: '3',
              }
            ]
          }
        ]
      }
    ]
}

tokens

abstract syntax tree

Compiler

Input

Parsing

Transformation

Code Generation

output

(add 2 (subtract 4 3))

abstract syntax tree

modified abstract syntax tree

add(2, subtract(4, 3));

Integration Test: Demo

Example of End 2 End testing 

Detox.js

Detox.js

  • End-to-end testing framework

  • Help automate manual QA process

  • Detox uses EarlGrey for iOS and Espresso for Android under the hood

  • Deep first-class support for Recat-Native

  • Made For CI: Execute your E2E tests on CI platforms like Travis

  • Integrates with jest.js

Detox Matchers

Detox uses Matchers to find UI `elements`

// by.id will match an id that is given to the view 
// via testID prop.
by.id()
// Find an element by text, useful for text fields, buttons.
by.text()
// Find an element by accessibilityLabel on iOS,
// or by contentDescription on Android.
by.label()
// Find an element by native view type.
by.type()
// In a React Native component add testID like so:
<TouchableOpacity testID={'tap_me'}>
// You can access the element using by.id function
const button = element(by.id('tap_me'))

Component.js

test.js

Actions

Actions emulate user interaction with those `elements`

// Functions

.tap()
.longPress()
.multiTap()
.tapAtPoint()
.tapBackspaceKey()
.tapReturnKey()
.typeText()
.replaceText()
.clearText()
.scroll()
.scrollTo()
.swipe()
// Example

const button = element(by.id('tap-me'));

button.tap();

Expectations

Expectations to verify value on those `elements`

// Functions

.toBeVisible()
.toBeNotVisible()
.toExist()
.toNotExist()
.toHaveText()
.toHaveLabel()
.toHaveId()
.toHaveValue()
// Example

const inputText = element(by.id('UniqueId204'))

expect(inputText).toBeVisible();

Demo

Any Questions?

Feedback

Links

Slides:

Jest.js:

Detox.js:

Demo 1:

Demo 2:

Video recording of this seminar:

THE END

Introduction to Automated Testing in JavaScript

By Sanjeev Yadav

Introduction to Automated Testing in JavaScript

This session is meant to give a brief introduction to testing along with how to write tests for your JavaScript Application. The talk is orientated towards novices and it would be a stepping stone towards writing test for your React/Angular projects.

  • 414