Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Learning BDD with Javascript (Distilled)

Learning BDD with Javascript (Distilled)

This is a distilled summary of the book "Learning Behavior Driven Development" by Enrique Amodeo, Packt, 2015.

https://www.packtpub.com/application-development/learning-behavior-driven-development-javascript

Avatar for jisfy

jisfy

May 04, 2018

Other Decks in Programming

Transcript

  1. mocha cheatsheet describe context beforeeach wraps together several Test Cases,

    creating a Test Suite for a common feature or behavior it wraps together several Test Cases that share a common set up or inputs sets up the Test Fixture that will be used by each Test Case in the same Context/Describe scope where beforeEach belongs. A new Fixture will be created before each Test Case is run provides the actual code for a Test Case
  2. CHAI cheatsheet chains flags assertions ADD EXPRESSIVITY, DO NOT MODIFY

    THE ACTUAL BEHAVIOR OF ASSERTIONS MODIFY THE ACTUAL BEHAVIOR OF ASSERTIONS PERFORM THE ACTUAL CHECK to, be, been, is, which, has, have, at... not, deep... equal, true, false, empty, undefined, exist, a, below, within, closeTo, most, throw...
  3. CHAI examples II expect([1, 2, 3]).to.have.length(3) expect([1, 2]).to.have.length.of.at.most(3) expect([1, 2]).to.have.length.of.at.least(1)

    expect({ name : 'Joe' }).to.include.keys('name') var cantSayHello = function () { throw new Error() } expect(cantSayHello).to.throw(Error)
  4. using sinon stubs II (provide fake method responses) (the real

    netSalary method is replaced with a Stub, telling it which value must be returned upon execution)
  5. ...or use sinon spies (to check for method calls) (without

    sinon-chai , calledOnce is called at the spy level)
  6. sinon cheatsheet stub spy mock IS A TEST DOUBLE WITH

    A CANNED RESPONSE IS A TEST DOUBLE WHICH CAPTURES INTERACTIONS IS A HYBRID OF A STUB AND A SPY
  7. Callback based apis Testing asynchronous (We will use the OrderSystem

    class as an example of Asynchronous, Callback based API. Most notably, its getOrders method, which accepts a callback function as an argument)
  8. Callback based apis II Testing asynchronous (we use a special

    kind of beforeEach function that accepts a callback. We call this callback function to signal Mocha that the set up of the fixture is complete) (the callback function accepts an error argument. If this argument is not null, Mocha will consider the whole Test Suite as failed) (only when the callback function done is called, will Mocha start running the Test Cases)
  9. promise based apis Testing asynchronous (This time, we will use

    an OrderSystem class that is Asynchronous, and Promise based. At least so long as the ordersRepository.all method returns a Promise)
  10. promise based apis II Testing asynchronous (we use the standard

    beforeEach) (The Promise must be returned at the end of the beforeEach block. Mocha will wait until the returned Promise is settled. Then run the Test Cases) (The Test Cases can be considered synchronous, at least as far as the fixture is concerned) (we make the 'all' method return a fulfilled Promise, to simulate a Promise based API) (we will rely on the Q Promise library)
  11. promise based apis III Testing asynchronous (An alternative when testing

    Promise based APIs is to not return a Promise in the beforeEach function. Instead we just store a reference to the Promise and let the Test Cases do the Handling) (In this example, we rely on Mocha's runtime context to store the Orders. Notice how we use 'this.orders'. Using 'this' we reference Mocha's runtime context, which is shared between all Test Cases) (The Test cases will wait instead for the Promise to settle. Unlike beforeEach, that will be synchronous this time)
  12. promise based apis IV Testing asynchronous (Tell Chai about chai-as-promised.

    chai-as-promised augments the standard Chai library, adding new flags and chains) (Having the assertions inside the Promise handler function makes it look a little verbose. Using chai-as-promised provides a syntactic sugar to better depict the handling of a Promise result. Use the 'eventually' flag to add assertions on the Promise result directly)
  13. Automating Tests with Mocha, Chai and Sinon Automating Tests with

    Mocha, Chai and Sinon Install mocha and chai: Install mocha and chai: update the scripts section of package.json update the scripts section of package.json ...run with npm test ...run with npm test A mocha Test A mocha Test ...with chai ...with chai chai cheatsheet chai cheatsheet Chai provides a DSL that supports chaining of three types of Particles CHAINS: add expressivity, do not modify the behavior of assertions to, be, been, is, which, has, have, at... Flags: modify the behavior of assertions not, deep... Assertions: perform the actual check equal, true, false, empty, undefined, exist, a... below, within, closeTo, most, throw Example: expect(1).to.be.ok expect(true).to.be.true expect(1).to.not.be.true expect(null).to.not.exist expect(undefined).to.not.exist expect(something).to.not.be.equal(other) expect(1).to.be.below(2) expect(1).to.be.at.most(2) expect(2).to.be.above(1) expect(1).to.be.at.least(1) expect(2).to.be.within(1, 3) expect(2.2).to.be.closeTo(2, 0.2) expect([1, 2, 3]).to.have.length(3) expect([1, 2]).to.have.length.of.at.most(3) expect([1, 2]).to.have.length.of.at.least(1) expect({ name : 'Joe' }).to.include.keys('name') var cantSayHello = function () { throw new Error() } expect(cantSayHello).to.throw(Error) Chai provides a DSL that supports chaining of three types of Particles CHAINS: add expressivity, do not modify the behavior of assertions to, be, been, is, which, has, have, at... Flags: modify the behavior of assertions not, deep... Assertions: perform the actual check equal, true, false, empty, undefined, exist, a... below, within, closeTo, most, throw Example: expect(1).to.be.ok expect(true).to.be.true expect(1).to.not.be.true expect(null).to.not.exist expect(undefined).to.not.exist expect(something).to.not.be.equal(other) expect(1).to.be.below(2) expect(1).to.be.at.most(2) expect(2).to.be.above(1) expect(1).to.be.at.least(1) expect(2).to.be.within(1, 3) expect(2.2).to.be.closeTo(2, 0.2) expect([1, 2, 3]).to.have.length(3) expect([1, 2]).to.have.length.of.at.most(3) expect([1, 2]).to.have.length.of.at.least(1) expect({ name : 'Joe' }).to.include.keys('name') var cantSayHello = function () { throw new Error() } expect(cantSayHello).to.throw(Error) npm install mocha chai –save-dev npm install mocha chai –save-dev ADDING A CONTEXT ADDING A CONTEXT beforeEach: to create the Test Fixture before each Test Case is run (the same Employee in our example ) beforeEach: to create the Test Fixture before each Test Case is run (the same Employee in our example ) context: to wrap together several Test Cases that share the same set up context: to wrap together several Test Cases that share the same set up describe: wrap together several Test Cases, creating a Test Suite for a common feature or behavior describe: wrap together several Test Cases, creating a Test Suite for a common feature or behavior
  14. Automating Tests with Mocha, Chai and Sinon Automating Tests with

    Mocha, Chai and Sinon A mocha, chai & sinon Test (stub) A mocha, chai & sinon Test (stub) sinon cheatsheet sinon cheatsheet Sinon-chai integration Sinon-chai integration STUB: A Stub is a Test Double with a canned response STUB: A Stub is a Test Double with a canned response Spy: A Spy is a Test Double which captures interactions Spy: A Spy is a Test Double which captures interactions mock: A Mock is a hybrid of a Spy and a Stub mock: A Mock is a hybrid of a Spy and a Stub Install sinon and sinon-chai: Install sinon and sinon-chai: npm install sinon sinon-chai –save-dev npm install sinon sinon-chai –save-dev Sinon-Chai augments the original Chai expect with additional assertions Sinon-Chai augments the original Chai expect with additional assertions Replaces the real netSalary method with a Stub, telling it which value must be returned upon execution Replaces the real netSalary method with a Stub, telling it which value must be returned upon execution Without the sinon- chai integration all we can do is check the calledOnce property of the spy to be true. Without the sinon- chai integration all we can do is check the calledOnce property of the spy to be true. With the sinon-chai integration in place, the calledOnce property becomes now a regular chai assertion With the sinon-chai integration in place, the calledOnce property becomes now a regular chai assertion
  15. Writing bdd features testing async features Writing bdd features testing

    async features Testing callback based apis Testing callback based apis When the Test Fixture requires asynchronous operations, we can rely on a special kind of beforeEach function that accepts a callback method as an argument. The callback must be called to signal that the setting up of the fixture is done. When signaled Mocha will start running the Test Cases. The done callback accepts an error parameter. If this parameter is not null, Mocha will consider the whole Test Suite failed. When the Test Fixture requires asynchronous operations, we can rely on a special kind of beforeEach function that accepts a callback method as an argument. The callback must be called to signal that the setting up of the fixture is done. When signaled Mocha will start running the Test Cases. The done callback accepts an error parameter. If this parameter is not null, Mocha will consider the whole Test Suite failed. The callsArgWithAsync method of a Sinon Stub, allows you to inform the Stub that it should consider the parameter with index “zero” as a call function, which it should call passing “null” and an empty array “[]” as the first and second arguments. The callsArgWithAsync method of a Sinon Stub, allows you to inform the Stub that it should consider the parameter with index “zero” as a call function, which it should call passing “null” and an empty array “[]” as the first and second arguments. Testing PROMISE based apis Testing PROMISE based apis If the API is based on Promises, we can rely on the standard version of the beforeEach function. Do not forget to return return the Promise at the end of the beforeEach function. This will inform Mocha of the Promise, and it will wait until the Promise settles to start calling the Test Cases. Returning the Promise serves the same purpose as calling the done function in the callback version. From this point on, we can consider the Test Cases to be synchronous, at least as far as the fixture is concerned. If the API is based on Promises, we can rely on the standard version of the beforeEach function. Do not forget to return return the Promise at the end of the beforeEach function. This will inform Mocha of the Promise, and it will wait until the Promise settles to start calling the Test Cases. Returning the Promise serves the same purpose as calling the done function in the callback version. From this point on, we can consider the Test Cases to be synchronous, at least as far as the fixture is concerned. Our Stubbed function returns a fulfilled Promise to simulate a Promise based API. Our Stubbed function returns a fulfilled Promise to simulate a Promise based API.
  16. Writing bdd features testing async features Writing bdd features testing

    async features Testing promise based apis II Testing promise based apis II An alternative when testing Asynchronous, Promise based APIS, is to not return the Promise in the beforeEach function. Instead, we just store a reference to the Promise in a variable, and let the Test Cases do the handling. Again, using the “then” method of a Promise, and performing the corresponding assertions in its body. With this solution, Mocha must not wait for any asynchronous operation in beforeEach to finish, but the Test Cases will instead. In the example we use Mocha's runtime context, to store the orders. Notice how we use “this”. We could have used a variable declared at the outer context scope. Mocha's runtime is shared by all Test Cases. An alternative when testing Asynchronous, Promise based APIS, is to not return the Promise in the beforeEach function. Instead, we just store a reference to the Promise in a variable, and let the Test Cases do the handling. Again, using the “then” method of a Promise, and performing the corresponding assertions in its body. With this solution, Mocha must not wait for any asynchronous operation in beforeEach to finish, but the Test Cases will instead. In the example we use Mocha's runtime context, to store the orders. Notice how we use “this”. We could have used a variable declared at the outer context scope. Mocha's runtime is shared by all Test Cases. Testing PROMISE based apis III Testing PROMISE based apis III Install chai-as-promised: Install chai-as-promised: npm install chai-as-promised –save-dev npm install chai-as-promised –save-dev Having the assertions inside the Promise handler function makes it look a little verbose. There is a way to augment Chai's capabilities, with Promise support. It is the module called chai-as-promised, which you will need to install. Do not forget to notify Chai about the new module. Once installed, you will be able to use the eventually chain, which is a syntactic sugar for handling of the Promise result. Having the assertions inside the Promise handler function makes it look a little verbose. There is a way to augment Chai's capabilities, with Promise support. It is the module called chai-as-promised, which you will need to install. Do not forget to notify Chai about the new module. Once installed, you will be able to use the eventually chain, which is a syntactic sugar for handling of the Promise result.