This project contains a set of exercises to help teach TDD. It will auto-compile your TypeScript code, run your tests and, enforce a minimum code coverage percentage (95%).
First clone this repository and change into the newly cloned directory. The rest of this guide assumes you are in the project's root directory when running commands.
$ git clone https://github.com/michikono/typescript-tdd-exercises
$ cd typescript-tdd-exercises
Then install all dependencies:
$ npm install
For these exercises, we will use Grunt to manage the build process.
This final step is the one that turns on the TDD process and is what you use going forward:
$ npm run watch
To run tests manually:
$ npm test
If you see the following, your setup process is complete:
To get notifications working, you may need to install the following:
- Install Growl
- Run
sudo gem install terminal-notifier
You can see code coverage analysis in two ways:
- Make a change while
grunt watch
is on and read the console - Run
grunt test
and read the console
Then visit the lcov report page (file will be missing if a coverage analysis has not been run)
You can find all of the grunt configurations in the grunt
folder. Here's what Grunt is doing:
- Compiled TypeScript output (JavaScript) goes to the
out
folder while preserving the original file/folder structure. - All of the
.js
files are then copied (concatenated) toout/test.js
andout/coverage.js
file. The source maps are preserved. - All
out/src/**/*.js
files are "instrumented" by Istanbul for code coverage analysis. The results are stored inout/instrument
. - Code coverage involves running all tests against this instrumented folder. The instrumented files are merged with
test files and placed in
out/coverage.js
. The file is executed. - Coverage results are captured in
coverage/
. - Coverage thresholds are configured in
grunt/coverage.js
and the data is pulled fromcoverage/reports/coverage.json
. - If any grunt process fails (e.g., a test or a coverage threshold) an error is shown and the rest of the jobs stop.
npm run watch
watches for code changes that trigger the above steps automatically as necessary. It is meant to be noisy if you are not writing passing tests.
Review the example project if you have questions about TypeScript.
- Pay special attention to nesting modules: top level modules don't use
export
, but children should. See more here: http://stackoverflow.com/questions/12991382/typescript-modules - TypeScript files should always start with a reference line (think of it as a header file) that links to references.ts using a relative path; for example:
/// <reference path="../../references.ts" />
- Executed JS is not kept as separate files. This is to avoid the complexity of using Node's
require
syntax in a TypeScript environment (although entirely doable). - You can find example files at
src/example/
andtest/example/
. - You can find instructions for individual exercises in the
src/
folder. - TypeScript declarations are found in
tsd.d.ts
, and are managed usingtsd
. They are like.h
files in other languages. If you end up using external libraries such as Underscore.js, you may want to install dependencies usingtsd install [name] --save
(more on this here: https://github.com/DefinitelyTyped/tsd) - Folders you may want to mark as excluded from your IDE's code index:
out/
,node_modules/
, andcoverage/
.
- This setup process borrows from the Typescript Starter repo
- You need to install
npm
(node
comes with it). This is because TypeScript compiles to JavaScript and without Node, you would need to run your code in a browser. Running sample snippets in a browser adds unnecessary complexity as compared to running Node scripts. - Testing is done using two libraries. One is Mocha, a framework for writing
assertions (the
assert
variable). The other is Sinon, a stubbing and mocking library (thesinon
andsandbox
variables). See examples of this in Driver tests. - As a convenience, all test modules have a
sandbox
variable that you can use to make stubs. It will clean up your mocks and stubs after each test run. You can mostly ignore this, but if you are curious why this was setup, you can find more about it here.