dwyl / learn-tape

:white_check_mark: Learn how to use Tape for JavaScript/Node.js Test Driven Development (TDD) - Ten-Minute Testing Tutorial
187 stars 31 forks source link

How should we be using `t.plan` and `t.end` in our tests? #12

Open samhstn opened 7 years ago

samhstn commented 7 years ago

I've been noticing a difference in the way we are using t.plan and t.end in our modules and in Dwyl's Science Museum Project

What are the merits of using t.plan along with t.end vs just using t.end (in most scenarios) and which pattern should we be following when writing tape tests and why?

@alanshaw I know you like using this pattern. What benefits have you found from the additional test planning.

alanshaw commented 7 years ago

It's a way of verifying the assertions you wanted to make were made.

Without t.plan it's possible (for example when juggling multiple async operations) to accidentally end a test before you've made any assertions - the test passes, but possibly shouldn't have. By using t.plan in combination with t.end you ensure this doesn't happen.

A contrived example:

Imagine if you were testing Async.each, without t.plan:

const Async = require('async')
const test = require('tape')

test('should call iterator function for each element', (t) => {
  const data = [1, 2, 3]
  const iteratee = (d, cb) => { t.ok(d); cb() }
  const callback = () => t.end()
  Async.each(data, iteratee, callback)
})

If Async.each is buggy and does not call the iterator function for each element, but does call the callback function then the test will pass - a false positive. Using t.plan(data.length) can prevent this.

nelsonic commented 5 years ago

This is worth adding to the readme in a "FAQ" section.