2.0.1 • Published 6 years ago

chai-approved v2.0.1

Weekly downloads
-
License
MIT
Repository
github
Last release
6 years ago

chai-approved

A simple Chai assertion helper for use with Mocha to make it easy to create "approval tests." See below for more info on approvals.

Rich Clingman -- github -- LinkedIn -- @richclingman

Sytnax

expect(text).to.be.approved(this)

expect(text).toBeApproved(this)

expect(object).to.be.approvedAsJSON(this)

expect(object).toBeApprovedAsJSON(this)

Version 1 vs. Version 2

Version 1

A call to Version 1 assertion passed the testName. I didn't like it, but couldn't think of a better way at the time.

expect('myString')
  .to.be.approved(this._runnable.fullTitle())

Version 2

Thank you cmstead for "this" idea.

expect('myString')
  .to.be.approved(this)

A call to Version 2 passes the entire Mocha context using "this". The helper decides what info it needs (currently only the testName). This was done to simplify the use of this assertion helper and to prepare for accessing configuration values and other info from Mocha within the helper.

There are no other changes between Version 1 and Version 2 other than updating and improving the tests, and tweaking README. However, since this is a "breaking change" to the interface, we've bumped the major version number.

Unit Test Approvals

Approval Tests allow easy unit testing of large blocks of text or objects without needing to declare the expected result. This is done by writing an "approved" file with the expected result. Each test run then compares the current run with the approved result. If there is a difference, a "received" file is created for easy comparison with a diff utility. After the failure, either the code is fixed, or the approved result is updated to match the received result. (If the approved file does not exist, an empty one is created by the assertion helper.)

Llewellyn Falco: ApprovalTests describes the concepts of approvals. Llewellyn Falco and others have created a set of libraries for creating approval tests in a variety of languages. I've learned to really love them. I've used them extensively at work and in many of my own projects.

Simple Approvals With Mocha/Chai

Llewellyn's libraries are awesome and versitile. I wanted to have some of the features in a vary small, simple to install, simple to use library. I chose to add them as Chai assertion helpers.

describe('getFullName', function() {
 it('should return customer first name + last name', function() {
   const aCustomerRecord = getCustomerRecord(1234);
   const result = aCustomerRecord.getFullName();
   expect(result).to.be.approved(this)
 })
})

When this test runs, it will look for an "...approved.txt" file based on testName and compare it to the results from this test. (See below about how files are named.)

When the test result matches approved file

The test passes. Any obsolete ...received.txt file is deleted. (See below.)

When the test result does not match approved file

The test fails. A "...received.txt" file is created with the contents of this test run.

When is no approved file exists

The test fails. An empty "...approved.txt" file is created. A "...received.txt" file is created with the contents of this test run.

Manually approve ...received.txt file

Currently, you must manually approve the ...received.txt file if it has the correct result.

  • If the ...received.txt is wrong, correct the code.
  • If the ...received.txt is correct, approve the results by renaming "...received.txt" to "...approved.txt" file.
  • Rerun the test.

Planned Diff Utility Integration

Once the feature is added, after a failure, we'll start a diff utility. Use the diff to compare the ...received.txt and ...approved.txt.

  • If the ...received.txt is wrong, correct the code.
  • If the ...received.txt is correct, approve the results in the diff (push to the ...approved.txt file and save).
  • Rerun the test.

peerDependencies Restrictions

This library is written to work as a Chai assertion helper running under Mocha. (It's where I need simple approvals to work.)

The package.json specifies peerDependencies for specific versions of chai and mocha. This is only because that's what I've tested them with. You're welcome to remove the peerDependencies and try with other versions. Please let me know where you find chai-approvals work. I expect it'll work with a wide range of versions, but I've only tested with one pair.

  "peerDependencies": {
    "chai": "^4.1.2",
    "mocha": "^5.2.0"
  },

Approval file location

Currently, the approved files are located in .../approvals/ below where the helper is located. Sorry, they end up inside node_modules at the moment.

It's planned to support a configuration setting to put the directory where desired (ex: below .../tests/ or .../specs/).

Approval file name

The full test name is used to generate the approval file names. The full test name is all the described and it block titles combined. Non-alphanumeric are removed and replaced by a dash. Alpha is forced to lower case. (See the note at the top about injecting the test name.)

In the example from above...

describe('getFullName', function() {
 it('should return customer first name + last name', function() {
   ...

The approved file will be

  • getfullname-should-return-customer-first-name-last-name.approved.txt

The received file will be

  • getfullname-should-return-customer-first-name-last-name.received.txt

By understanding the naming, you're able to find the exact test that created the file(s). **Because the describe/it blocks decide the filenames, the combination of describe/it values must always be unique. Otherwise, multiple tests will be comparing their results to the same ...approved.txt file.

Chai Assertion Helpers

.to.be.approved()

The string passed to expect() is compared to the approved file.

expect(stringResult)
  .to.be.approved(this)

.toBeApproved()

An alias to the function above.

expect(stringResult)
  .toBeApproved(this)

.to.be.approvedAsJSON()

The object passed to expect() is JSON.stringify()'d and the result is compared to the approved file.

expect(objectResult)
  .to.be.approvedAsJSON(this)

.toBeApprovedAsJSON()

An alias to the function above.

expect(objectResult)
  .toBeApprovedAsJSON(this)
2.0.1

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago