How can we verify that our code is correct?
Mocha and Chai - still probably the most widely used library New library people are liking a lot more
LambdaSchool - Testing
You're going to have a couple of folders In the folders, some boilerplate code written
This is not a test-driven approach, it's unit testing You'll take some code that's already there and write unit tests.
We'll use Jest (a library)
LambdaSchool creating a council made of industry experts and hiring partners Every three months, check curriculum against what the partners need
Start with Basic Javascript You're going to work inside the spec folder to test the functionality of the particular file you're testing
It's not just about writing tests, it's about getting familiar with a code base you didn't write
As part of this, if you see that there's some edge cases a function doesn't take into account, you could ask the client and ask 'What happens if someone tries to add 10 to something that is empty?" I know this is undefined, but I ask them "Do you want to return 0 or do you want it to be empty?" "Well, if it's undefined, I want a 0." Now you have a new spec. If you want to, feel free to make the code you see more correct
In C#, never have to check if something is a number because it's a strongly typed language
Confidence ( in the sense of trusting your code ) Verifying correctness
We write code to test our code.
Writing code to check our code is something we know how to do.
Which libraries should I use for testing?
We are using Jest.
Automated testings mean you don't have to manually test everything, you can let the system run and test for you and call your attention to things that failed
If you have automated tests, even if it's a large code-base, you can run tests before deploying to production
unit tests (fastest)
integration tests
end to end (slow)
functional testing
acceptance test
Ex: Think you're building hardware instead of software and you build a TV
When you're installing Jest, it could be a dev dependency but what happens in some companies is your tests get run as part of the build process.
So you need to have Jest as a dependency so that the automated process on the server can also get the package
In Jest, jest is going to run tests two ways (common ways)
Jest has a few Globals
it('run the tests', () => {})
As long as second argument is a function, this is a valid function
"scripts": {
"test": "jest" // does not subscribe to changes
}
yarn start
function add(a, b) {
return a + b;
}
module.export = {
add: add,
};
Since we're usiung Node, we need to export functions from other files
If you were doing everything on create-react-app, it would be transpiled and work
it('should add two numbers', () => {
// arrange (where you set up environment)
const expected = 5
const add = require('../index').add;
// act
const actual = add(3, 4);
// assert - jest matchers/assertions
expect(actual).toBe(expected) // result: fail
})
Another way to import function:
const sut = require('../index)
const utilities = require('../index');
it ('should add two numbers', () => {
const expected = 7
const add = utilities.add;
const actual = add(3,4);
expected(actual).toBe(expected)
})
sut = system under test refers to something you're testing
Always fail first
"scripts": {
"tests": "jests --watchAll" // updates on save
}
Watch Usage:
> Press f to run only failed tests
> Press o to only run tests related to changed files
> Press p to filter by a filename regex pattern
> Press t to filter by a test name regex pattern
> Press q to quit watch mode
> Press Enter to trigger a test run
Some people do:
it('should add two numbers', () => {
const expected = 7;
const add = utilities.add;
const actual = add(3, 4);
expect(actual).toBe(7)
})
Don't do this:
it('should add two numbers', () => {
const expected = 7
const add = utilities.add;
const actual = add(3,4);
expected(add(3,4)).toBe(7)
});
Don't in-line the execution of the code of the system under test into the expected
You want your code to be easier to read for people
This is a simple example, but sometimes executing the function will require a lot more than that and if you in-line it ...
Facebook has it inline to save space maybe?
In reality, you'll be testing React applications so instead of using require, you'll be using import and export This is a problem that's going to go away, so don't worry too much about this (requiring the file)
I feel okay. You're going to hear a lot of opinion this week. Doesn't really matter.
The way I approach it, I am testing a bit of functionality.
I don't want to have create five functions when I could have one with all the setup and then have a few more expects.
I'm okay with something like this:
it('should add two numbers', () => {
const add = utilities.add;
const seven = add(3,4)
const four = add(0,4)
const minusthree = add(1,-4);
expect(seven).toBe(7);
expect(four).toBe(4);
expect(minusthree).toBe(-3);
})
When you don't have a git repository, you need to use --watchAll
If it's a git repository, you can use --watch
Jest is really smart. It will only run when the test or the code changes. If you change code and there's no test associated with it, it won't run. It will auto-test if you have the --watch or --watchAll
Quick Intro of what Matchers are: https://facebook.github.io/jest/docs/en/using-matchers.html
API on Matchers: https://facebook.github.io/jest/docs/en/expect.html#methods
Globals: https://facebook.github.io/jest/docs/en/api.html
Options for the CLI: https://facebook.github.io/jest/docs/en/cli.html
You can group tests by whatever you're testing.
const utilities = require('../index');
describe('default', () => {
it('run the tests', () => {})
});
describe('add function, () => {
it('should add two numbers', () => {
// arrange
const add = utilities.add;
//act
const seven = add(3,4);
const four = add(0, 4);
const minusThree = add(1, -4);
//assert
expect(seven).toBe(7);
expect(four).toBe(4);
expect(minusThree).toBe(-3);
});
});
Describe: A global that's a way for you to organize pieces of code and the display of the code.
it('checks identity', () => {
const numbers = [1, 2, 3];
const actual = [1, 2, 3]; // comes from executing code
expect(numbers).toBe(actual) <---fails test
})
it('checks identity', () => {
const numbers = [1, 2, 3];
const actual = [1, 2, 3];
expect(numbers).toEqual(actual); <---passes tests
})
Yes. This is why I called it checks identity, because one of them will check not only is the content equal, but it will check for the content. It's a deep equal, so it'll check if all the values and properties are the same.
it('checks identity', () => {
const numbers = [1, 2, 3];
const actual = numbers; // actual is now a reference to numbers
expect(numbers).toBe(actual);
// passes tests because they have the same identity, the same reference, the same pointer
})
People tend to use toBe and toEqual and they sometimes feel the same, but they're not really the same.
What if I want to check the type of something?
it('checks that it is an array', () => {
const numbers = [1, 2, 3];
const expected = 'array'
const actual = typeof numbers
expect(numbers).toBe(expected) // failed - expected value to be 'array', received 'object'
})
You want to do checks as specialized as you can. Do not rely on toBe or toEqual to do all of your tests.
Take a look at the Methods Go with whatever makes the code more readable.