Last active
September 26, 2018 21:21
-
-
Save Anna-Myzukina/b3ffd40b84142ce050b093e8cddbaa0c to your computer and use it in GitHub Desktop.
test-anything
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Exercise 1 | |
var emotify = require(process.argv[2]) | |
console.log(emotify(process.argv[3])) | |
/* | |
# Log it out | |
Developing apps and modules is fun. However often you might be concerned whether | |
things work or when you add new features you want to be sure you did not break | |
anything. Therefore developers invented tests for their well-being. They allow | |
you to automatically, well, test your application or module. | |
Let's assume you wrote a function called emotify, which takes a String and | |
adds a space and a :) to it. How would you check that your function is | |
working? | |
Maybe your first idea was calling the function with a value and console.log | |
the result and then check its output in the console. | |
var emotify = require('./emotify.js') | |
console.log(emotify('just testing')) | |
Try this yourself. We are going to provide the location for the awesome | |
emotify module in process.argv[2] and the String for the test in | |
process.argv[3].*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Exercise 2 | |
var isCoolNumber = require(process.argv[2]); | |
var assert = require('assert'); | |
assert.ok(isCoolNumber(42),"OK!"); | |
/** | |
# Tell me what's wrong | |
Write a passing assertion for the function isCoolNumber, that will assure that | |
it returns true when passing 42 in it. | |
The path of the module exporting the function will be provided through | |
process.argv[2]. | |
------------------------------------------------------------------------------------------------------------ | |
## Hints | |
Well this was probably nothing new for you. But wait don't leave, we are going | |
to learn about some better ways to do this. | |
If you are wondering, what's wrong about console.log, then think about this: | |
If your functions are going to be more complex it is going to be harder and | |
harder to actually read the output. You have to know what output is expected for | |
every input and for different functions. | |
So it would be better if our tests only told us about whether something works or | |
not. Surely we could probably test each output with !== and warn if something | |
is wrong like this. | |
if(add(2,1) !== 3) throw new Error('add(2,1) should be 3') | |
Now we get an error every time something is wrong, with the message what's not | |
working. However in node there is a nice built-in module for this called | |
assert. | |
var assert = require('assert') | |
assert(add(2,1) === 3,'add(2,1) should be 3') | |
Or as alternatively: | |
assert.deepEqual(add(2,1), 3, 'add(2,1) should be 3') | |
Here are some functions you can use with assert. For a full list, see the | |
documentation. | |
assert.ok(value, message) // tests if value is truthy | |
assert.equal(actual, expected, message) // == | |
assert.notEqual(actual, expected, message) // != | |
assert.deepEqual(actual, expected, message) // for comparing objects | |
assert.notDeepEqual(actual, expected, message) | |
assert.strictEqual(actual, expected, message) // === | |
assert.notStrictEqual(actual, expected, message) // !== | |
## Resources | |
* Node documentation: http://nodejs.org/api/assert.html | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Exercise 3 | |
var test = require('tape'), | |
fancify = require(process.argv[2]); | |
test('fancify function', function(t) { | |
t.equal(fancify('Hello'), '~*~Hello~*~', 'wraps string in ~*~~*~'); | |
t.equal(fancify('Hello', true), '~*~HELLO~*~', 'converts the string into ALLCAPS, wraps in ~*~~*~'); | |
t.equal(fancify('Hello', false, '!'), '~!~Hello~!~', 'optional argument that determines the character'); | |
t.end(); | |
}); | |
/* | |
# Tape it together | |
Write tests that output TAP, that tests the following properties of a function | |
fancify. The function will be provided in process.argv[2]. | |
1 fancify(str) returns the str wrapped in ~*~ | |
Example: fancify('Hello') returns ~*~Hello~*~ | |
2 It takes an optional second argument that converts the string into ALLCAPS | |
Example: fancify('Hello', true) returns ~*~HELLO~*~ | |
3 It takes a third optional argument that determines the character in the middle | |
Example: fancify('Hello', false, '!') returns ~!~Hello~!~ | |
## Hints | |
Testing with assert still has some downsides. Even though we don't have to | |
check all the values ourself like in the first level, but now we only get not | |
very readable errors when something is wrong. Otherwise our tests don't do | |
anything. Maybe we still would like to see some information that everything is | |
ok. | |
There is a standard for outputting data from tests called TAP, the | |
Test Anything Protocol. It is nicely readable for humans as well as for our | |
robotic friends. | |
One module for testing that outputs TAP is tape (another one is tap, duh). | |
It takes a description of what you are testing and a callback function, with a | |
parameter t that works quite similar to assert. You use it to write your | |
assertions. However it also has a function t.end(), that you call when you are | |
done with your assertions. | |
The tape module is not included in Node, so you need to install them in your | |
project folder (where you keep your exercise files) with npm install tape. | |
Here is an example how to test the last function with tape | |
var test = require('tape') | |
var isCoolNumber = require('./cool.js') | |
test('isCoolNumber accepts only cool numbers', function (t) { | |
t.ok(isCoolNumber(42), '42 should be cool') | |
t.end() | |
}) | |
## Resources | |
* TAP on Wikipedia http://en.wikipedia.org/wiki/Test_Anything_Protocol | |
* The tape module https://www.npmjs.org/package/tape*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Exercise 4 | |
var test = require('tape'), | |
repeatCallback = require(process.argv[2]); | |
test('repeatCallback function', function(t) { | |
t.plan(4); | |
repeatCallback(4, function() { | |
t.pass('Callback called successfully'); | |
}); | |
}); | |
/* | |
# Call me maybe | |
Write a test for a function repeatCallback(n, cb), that calls the callback | |
cb exactly n times. n can be any number you want in your test code. | |
As before the functions location will be provided through process.argv[2]. | |
## Hints | |
Sometimes we are not simply checking return values of functions. A lot in | |
JavaScript and node happens through callbacks and events. For this we often want | |
to know: Was that callback called or not? | |
The event-driven nature of JavaScript is also the reason why we had to call the | |
t.end() function in the last level. The test has to know whether we are done. | |
However there is maybe a better way to do this with callbacks using t.plan(n). | |
When we call this in the beginning we can tell tape how many assertions we are | |
doing. | |
var test = require('tape') | |
test('nextTick', function (t) { | |
t.plan(1) | |
process.nextTick(function () { | |
t.pass('callback called') | |
}) | |
}) | |
In this example we only have one callback, which will simply pass the test when | |
it is called. So we could have used t.end() within the callback instead. | |
However you might see, that if we had multiple callbacks in our tests the | |
t.plan(n) would come in handy. | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Exercise 5 | |
var tape = require('tape'), | |
feedCat = require(process.argv[2]); | |
tape('feedCat function', function(t) { | |
t.plan(3); | |
t.equal(feedCat('fish'), 'yum', 'will return str "yum"'); | |
t.equal(feedCat('chicken'), 'yum', 'will return str "yum"'); | |
t.throws(function() { | |
feedCat('chocolate'); | |
}); | |
}); | |
/* | |
# To err is human | |
A function feedCat takes any kind of food as a String argument and returns | |
'yum' for everything you feed them. However if you try to feed the cat | |
'chocolate', the function will throw an error. | |
Write tests for feedCat to be sure kittens can be fed yummy food without | |
being harmed. | |
The function will be provided through process.argv[2]. | |
## Hints | |
To err is human, to purr feline. - Robert Byrne | |
Chocolate is awesome and so are cats. However they do not make a wonderful | |
combination. The Caffeine and Theobromine in the chocolate can harm cats as well | |
as dogs. | |
Feeding chocolate to cats would therefore be considered an error. One way in | |
JavaScript to deal with errors is to throw them (even though in Node this is | |
probably not the best way). | |
If we want to deal with these errors, we can use try and catch like this: | |
try { | |
petDog('bordercollie') | |
} | |
catch(err) { | |
console.error('It seems like it doesn\'t like that.') | |
} | |
When we test things, we often say that we want to make sure that there are no | |
errors. Well, that is not entirely true. We certainly want error-free code. | |
However if someone else tries to do something weird with our functions, it | |
still might be good to see an error. So good that we might want to test this | |
behavior, e.g. to make sure there is no chocolate fed to cats. | |
So maybe we know that a dachshund does not like to be petted. Well we could test | |
this behavior like this: | |
t.throws(function () { | |
petDog('dachshund') | |
}) | |
Now the test expects an error and throws an error if there is no error. Mind | |
boggling, right? | |
By the way, if you are familiar with functional javascript, you might already | |
know that you could also write it in one line: | |
t.throws(petDog.bind(null, 'dachhund')) | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment