Better JS testing with Jasmine BDD Testing Framework
Tags: angular, testing, webdev, javascript
Published: 2021-03-01 20:29:03

**Jasmine** is a **behavior-driven development** framework for testing **JavaScript** code by describing acceptance criteria in terms of scenarios. Once system fulfills all acceptance criteria it is behaving correctly. Applying BDD approach to writing tests improves application quality and maintainability, and serves as a **live documentation**.

>We started describing the acceptance criteria in terms of scenarios, which took the following form:
>* Given some initial context (the givens),
>* When an event occurs,
>* then ensure some outcomes.
>
>[https://dannorth.net/introducing-bdd/](https://dannorth.net/introducing-bdd/)

BDD approach to testing provides a template for capturing story’s acceptance criteria as a set of sentences, like in the real conversation. At the same time it provides an answer on:
* where to start when writing tests
* what to test and what not to
* how much to test in one go
* what to call a tests
* how to understand why test fails

For more details check Dan North’s blog at [https://dannorth.net/introducing-bdd/](https://dannorth.net/introducing-bdd/)

# Core concepts

**NOTE:** Core Jasmine functionalities are described using pseudo code.

In terms of **BDD**, **Jasmine** provides `describe()` function which serves as a container for a group of related specifications tests (story, feature, scenario). In addition to that, Jasmine provides `it()` function that’s used as a container for a specification behaviour validation (acceptance criteria, specification, spec). Desired specification implementation behaviour is verified via expectations. 

* Used together, **describe**, **it** and **expectations** helps express story and acceptance criteria as a complete sentence / conversation

```js
describe('an order')
  it('sums the prices of its line items')
    expect(order.total == 100.00)
```

* **Matcher** implements a boolean comparison between the actual value and the expected value. It is responsible for reporting to Jasmine if the expectation is true or false. Jasmine will then pass or fail the spec.

```js
describe('an order')
  it('sums the prices of its line items')
    expect(order.total).not.toBe(0.00)
    expect(order.total).toBe(100.00)
```

* **Hooks** in Jasmine can be used to provide shared setup and/or tear-down before/after each specification in describe block is called

```js
describe('an order')
  beforeAll('run once before all specs are called')

  beforeEach('run before each spec is called')

  it('sums the prices of its line items')
    expect(order.total == 100.00)

  afterAll('run tear-down once after all of the specs are called')
  
  afterEach('run tear-down after each of the specs is called.')
```

* **Spies** provides a test double function. A spy can stub any function and track calls to it and all its arguments

```js
describe('an order printer')
  
  spyOn('printerObject', 'printOrderMethod')

  it('prints the order')
    printerObject.printOrderMethod()
    expect(printerObject.printOrderMethod() to have been called)
```

* Jasmine also provides a mock **Clock** object that can be used to test time dependent code and mock dates.
**NOTE:** It is important to uninstall the clock after the test to restore the original functionality!

```js
describe('clock')
  
  beforeEach()
    jasmine.clock.install()

  afterEach()
    jasmine.clock().uninstall();

  it('sets the clock to tomorrow')
    jasmine.clock().mockDate(tomorrow)
    jasmine.clock.tick(1 day)
    expect (currentDate === tomorrow)
```

* Testing code that requires **asynchronous** operations is supported by Jasmine. There are three ways to indicate a function is asynchronous:
  * by taking an optional callback parameter, 
  * by returning a promise, 
  * or by using the async keyword in environments that support it.

**BONUS**
* Check simple business scenario implemented with Jasmine BDD testing framework at: 
[All Things Angular - Jasmine BDD Testing Framework #angular] (https://allthingsangular.com/jasmine-bdd-testing-framework/#basic-setup-with-angular)
* Check custom Jasmine configuration example at: 
[All Things Angular - Jasmine BDD Testing Framework #Multiple Jasmine run configurations](https://allthingsangular.com/jasmine-bdd-testing-framework/#bonus)

# Conclusion

Having out of the box integration with Jasmine BDD testing framework, Angular provides everything needed to start building high quality testable applications. Applying BDD approach to software development assures that story’s acceptance criteria are working as expected and are bringing business value.