Lecture Notes Of Class 22:
Unit Testing with Mocha and Chai
Objective:
By the
end of this class, you should understand unit testing and how to write tests
for individual components of your code using Mocha and Chai.
What
is Unit Testing?
Unit
testing is the practice of testing individual units or components of a program
in isolation. The purpose of unit testing is to ensure that each part of your
program works as expected. This is a critical part of the software development
process because it helps identify and fix bugs early on, improving the overall
quality and reliability of your code.
Why
Unit Testing?
1.
Early Bug Detection: Catch bugs early
during development.
2.
Refactoring Confidence: When you change
or refactor code, unit tests ensure that everything still works.
3.
Documentation: Well-written unit tests
can serve as documentation for your code's behavior.
4.
Improved Design: Writing tests forces
you to think about the design of your code, leading to cleaner, more modular,
and testable code.
Tools
for Unit Testing in Node.js
- Mocha:
A testing framework for Node.js that provides functions like
describe,it, andbeforeEachto organize your tests. - Chai:
An assertion library that works with Mocha to validate the expected output
of your code. It provides assertions like
should,expect, andassertto check if the output matches the expected value.
Mocha:
The Testing Framework
Mocha
helps organize your tests in a structured manner. You define test cases using
the following methods:
describe(): A function that groups related tests together.it(): A function that defines a single test case.beforeEach()andafterEach(): Functions that run before or after each test, useful for setting up or cleaning up test data.before()andafter(): Functions that run once before or after all tests, typically used for global setup/teardown.
Chai:
The Assertion Library
Chai
provides different styles of assertions, and the most commonly used ones are:
expect(): A BDD-style assertion.assert(): An assertion that works in an assertion-based style.should(): An extension of the expect style that adds should-like syntax to objects.
Example:
jsconst expect = require('chai').expect; expect(4).to.equal(4); // This will passexpect(4).to.equal(5); // This will fail
Example
Code: Setting Up Mocha and Chai
1.
Install Mocha and Chai
To
start using Mocha and Chai, you'll need to install them in your Node.js
project.
bashnpm install --save-dev mocha chai
2.
Create a Test File
You
can create a test
folder in your project and add test files inside it. For example, create a file
called mathTest.js.
jsconst expect = require('chai').expect;const add = (a, b) => a + b; describe('Math Functions', function() { describe('add()', function() { it('should return the sum of two numbers', function() { const result = add(2, 3); expect(result).to.equal(5); }); });});
3.
Running Tests
Add a
test script to your package.json
to run Mocha:
json"scripts": { "test": "mocha"}
Now,
you can run the tests using the command:
bashnpm test
Lab
Tasks:
1. Write
Tests for Different Functions
Let's
consider a simple calculator
module that has three functions: add(),
subtract(),
and multiply().
First,
define the functions you want to test:
js// calculator.jsconst add = (a, b) => a + b;const subtract = (a, b) => a - b;const multiply = (a, b) => a * b; module.exports = { add, subtract, multiply };
Now,
write unit tests for these functions.
js// test/calculatorTest.jsconst expect = require('chai').expect;const calculator = require('../calculator'); describe('Calculator', function() { describe('add()', function() { it('should return the sum of two numbers', function() { expect(calculator.add(2, 3)).to.equal(5); }); }); describe('subtract()', function() { it('should return the difference of two numbers', function() { expect(calculator.subtract(5, 3)).to.equal(2); }); }); describe('multiply()', function() { it('should return the product of two numbers', function() { expect(calculator.multiply(2, 3)).to.equal(6); }); });});
2. Use
Assertions from Chai to Validate the Output
In the
test cases above, we've used expect()
to check if the actual output of the function matches the expected output. Some
other assertions you can use are:
.to.equal(): Checks if two values are equal..to.be.a('type'): Checks if a value is of a particular type (e.g.,string,number, etc.)..to.be.true: Checks if a value istrue..to.be.false: Checks if a value isfalse..to.be.null: Checks if a value isnull..to.have.lengthOf(): Checks if an array or string has a specific length.
Example:
jsexpect([1, 2, 3]).to.have.lengthOf(3);
Conclusion
Unit
testing is an essential part of software development. By using tools like Mocha
and Chai, you can test individual components of your code to ensure they work
as expected. Mocha helps you organize and run tests, while Chai provides a
powerful assertion library to validate your code's output.
In this
class, we learned how to:
- Set
up Mocha and Chai in your project.
- Write
unit tests for simple functions.
- Use
Chai assertions to validate the results of your functions.
Next
Steps:
- Practice
writing unit tests for other components of your project.
- Explore
more advanced testing techniques, such as testing asynchronous code with
Mocha and Chai.
You
said:
WRITE 10 ASSIGNMENTS FROM
ABOVE CONCEPT WITH STEP BY STEP SOLUTIONS with proper explanation in details
ChatGPT
said:
Assignments
on Unit Testing with Mocha and Chai
Here are
10 assignments based on the concept of unit testing with Mocha and Chai. Each
assignment includes a step-by-step explanation and detailed solutions.
Assignment
1: Testing a Simple Addition Function
Task:
Write a
unit test for a function add(a,
b) that returns the sum of two numbers.
Solution:
1.
Function to Test:
jsconst add = (a, b) => a + b;
2.
Test Case:
jsconst expect = require('chai').expect;const add = require('./add'); // Assume add function is in a separate file describe('add()', function() { it('should return the sum of two numbers', function() { const result = add(2, 3); expect(result).to.equal(5); });});
3.
Explanation:
o We
use describe() to group
our tests for the add() function.
o Inside
it(), we test whether
add(2, 3) equals 5.
Assignment
2: Testing a Subtraction Function
Task:
Write a
unit test for a function subtract(a,
b) that returns the difference between two numbers.
Solution:
1.
Function to Test:
jsconst subtract = (a, b) => a - b;
2.
Test Case:
jsconst expect = require('chai').expect;const subtract = require('./subtract'); describe('subtract()', function() { it('should return the difference of two numbers', function() { const result = subtract(5, 3); expect(result).to.equal(2); });});
3.
Explanation:
o This
test checks if the subtract() function
correctly calculates the difference between two numbers.
Assignment
3: Testing Multiplication Function
Task:
Write a
unit test for a function multiply(a,
b) that returns the product of two numbers.
Solution:
1.
Function to Test:
jsconst multiply = (a, b) => a * b;
2.
Test Case:
jsconst expect = require('chai').expect;const multiply = require('./multiply'); describe('multiply()', function() { it('should return the product of two numbers', function() { const result = multiply(2, 3); expect(result).to.equal(6); });});
3.
Explanation:
o This
test checks if the multiply() function
calculates the correct product.
Assignment
4: Testing Division Function with Edge Cases
Task:
Write a
unit test for a function divide(a,
b) that returns the quotient of two numbers. Handle the edge case
where b = 0.
Solution:
1.
Function to Test:
jsconst divide = (a, b) => { if (b === 0) { throw new Error('Cannot divide by zero'); } return a / b;};
2.
Test Case:
jsconst expect = require('chai').expect;const divide = require('./divide'); describe('divide()', function() { it('should return the quotient of two numbers', function() { const result = divide(6, 2); expect(result).to.equal(3); }); it('should throw an error when dividing by zero', function() { expect(() => divide(6, 0)).to.throw('Cannot divide by zero'); });});
3.
Explanation:
o We
handle the division by zero error using a throw.
o The
test checks if the function correctly throws an error when b = 0.
Assignment
5: Testing String Length Function
Task:
Write a
unit test for a function getStringLength(str)
that returns the length of a given string.
Solution:
1.
Function to Test:
jsconst getStringLength = (str) => str.length;
2.
Test Case:
jsconst expect = require('chai').expect;const getStringLength = require('./getStringLength'); describe('getStringLength()', function() { it('should return the length of the string', function() { const result = getStringLength('hello'); expect(result).to.equal(5); });});
3.
Explanation:
o The
test checks if the getStringLength()
function correctly returns the length of a string.
Assignment
6: Testing Array Element Existence
Task:
Write a
unit test to check if a specific element exists in an array using includes().
Solution:
1.
Function to Test:
jsconst contains = (arr, value) => arr.includes(value);
2.
Test Case:
jsconst expect = require('chai').expect;const contains = require('./contains'); describe('contains()', function() { it('should return true if the array contains the value', function() { const result = contains([1, 2, 3], 2); expect(result).to.be.true; }); it('should return false if the array does not contain the value', function() { const result = contains([1, 2, 3], 4); expect(result).to.be.false; });});
3.
Explanation:
o We
use includes() to check
if the array contains the specified element and validate the result using Chai
assertions.
Assignment
7: Testing an Asynchronous Function
Task:
Write a
test for an asynchronous function fetchData()
that returns data from an API. Use done()
in Mocha to handle the asynchronous nature.
Solution:
1.
Function to Test:
jsconst fetchData = (callback) => { setTimeout(() => { callback('Data received'); }, 1000);};
2.
Test Case:
jsconst expect = require('chai').expect;const fetchData = require('./fetchData'); describe('fetchData()', function() { it('should return data asynchronously', function(done) { fetchData((data) => { expect(data).to.equal('Data received'); done(); // Tells Mocha the test is complete }); });});
3.
Explanation:
o This
test uses done() to tell Mocha
when the asynchronous operation is complete.
Assignment
8: Testing Object Properties
Task:
Write a
unit test to check if an object has a specific property using Chai's .to.have.property().
Solution:
1.
Function to Test:
jsconst person = { name: 'John', age: 30,};
2.
Test Case:
jsconst expect = require('chai').expect; describe('person object', function() { it('should have a property "name"', function() { expect(person).to.have.property('name'); }); it('should have a property "age"', function() { expect(person).to.have.property('age').that.is.a('number'); });});
3.
Explanation:
o This
test checks if the object has the specified properties and validates their
types.
Assignment
9: Testing Array Length
Task:
Write a
unit test to check if an array has a specific length using .to.have.lengthOf().
Solution:
1.
Function to Test:
jsconst arr = [1, 2, 3, 4];
2.
Test Case:
jsconst expect = require('chai').expect; describe('Array length', function() { it('should have a length of 4', function() { expect(arr).to.have.lengthOf(4); });});
3.
Explanation:
o The
test ensures that the array has the correct number of elements.
Assignment
10: Testing Function with Multiple Parameters
Task:
Write a
unit test for a function multiplyAndAdd(a,
b, c) that multiplies a
and b, then
adds c.
Solution:
1.
Function to Test:
jsconst multiplyAndAdd = (a, b, c) => a * b + c;
2.
Test Case:
jsconst expect = require('chai').expect; describe('multiplyAndAdd()', function() { it('should multiply a and b, then add c', function() { const result = multiplyAndAdd(2, 3, 4); expect(result).to.equal(10); });});
3.
Explanation:
o The
test verifies that the function correctly performs multiplication and addition.
These
assignments will help students practice the various aspects of unit testing
with Mocha and Chai, from testing basic arithmetic functions to handling
asynchronous operations and working with arrays and objects.
You
said:
WRITE 50 no of MCQs only
FROM ABOVE CONCEPT with explanation
ChatGPT
said:
Here are 50 Multiple Choice Questions (MCQs) based on the concept of Unit Testing with Mocha and Chai, along with explanations for each
answer:
1.
Which of the following is the main purpose of unit testing?
a) To
test the entire system
b) To test individual components or functions
c) To deploy the application
d) To check the user interface
Answer: b) To test individual components or
functions
Explanation: Unit testing is aimed at testing
small units or functions in isolation to ensure they work as expected.
2.
What does Mocha provide in unit testing?
a)
Assertion library
b) Test framework for organizing tests
c) A GUI interface for testing
d) A tool to monitor performance
Answer: b) Test framework for organizing
tests
Explanation: Mocha is a testing framework that
provides structure and utilities for writing and organizing tests.
3.
What does the Chai assertion library allow you to do?
a)
Organize tests into suites
b) Write tests for database queries
c) Validate the output of your functions
d) Compile code
Answer: c) Validate the output of your
functions
Explanation: Chai is an assertion library used in
Mocha for validating whether the actual output of a function matches the
expected result.
4.
Which method in Mocha is used to group related tests?
a) it()
b) before()
c) describe()
d) done()
Answer: c) describe()
Explanation: describe()
is used to group related tests together for better organization.
5.
Which of the following is an example of a Chai assertion?
a)
assert.equal()
b) describe()
c) it()
d) before()
Answer: a) assert.equal()
Explanation: assert.equal()
is a Chai assertion used to check if two values are equal.
6.
What is the correct way to run Mocha tests from the terminal?
a) npm
start
b) npm test
c) mocha run
d) mocha start
Answer: b) npm test
Explanation: The command npm test runs Mocha tests if
Mocha is properly set up in the project.
7.
What function does Mocha’s it() perform?
a) It
groups related tests
b) It contains a single test case
c) It defines the setup of tests
d) It cleans up after tests
Answer: b) It contains a single test case
Explanation: it()
is used to define a single test case within a suite.
8.
Which of the following is the default assertion style in Chai?
a) Should
b) Expect
c) Assert
d) None of the above
Answer: b) Expect
Explanation: The default assertion style in Chai
is expect,
which allows for a readable, human-friendly way of asserting values.
9.
What is the purpose of Mocha’s beforeEach()?
a) It
runs before all tests
b) It runs after all tests
c) It runs before each test
d) It cleans up after each test
Answer: c) It runs before each test
Explanation: beforeEach()
is a hook in Mocha that runs before each test in a test suite.
10.
How can you handle asynchronous tests in Mocha?
a) Using
done() callback
b) Using expect()
c) Using assert()
d) Using setTimeout()
Answer: a) Using done() callback
Explanation: Mocha provides the done() callback to handle
asynchronous tests by signaling when the test is complete.
11.
Which of the following is used to check equality in Chai assertions?
a)
expect.to.equal()
b) assert.toEqual()
c) it.to.equal()
d) describe.to.equal()
Answer: a) expect.to.equal()
Explanation: expect.to.equal()
is used to check if two values are equal in Chai's assertion style.
12.
Which method would you use to check if a number is a specific type using Chai?
a)
.to.be.true
b) .to.be.a('number')
c) .to.equal()
d) .to.be.null
Answer: b) .to.be.a('number')
Explanation: Chai’s .to.be.a('number')
is used to check if a value is of type number.
13.
What does the .to.have.property() assertion in Chai check?
a)
Whether a string contains a substring
b) Whether an object has a specific property
c) Whether an array contains a specific element
d) Whether a number is divisible by another number
Answer: b) Whether an object has a specific
property
Explanation: .to.have.property()
checks if the given object contains the specified property.
14.
Which of the following is used to check if an array has a specific length in
Chai?
a)
.to.have.length()
b) .to.length()
c) .to.have.lengthOf()
d) .to.lengthOf()
Answer: c) .to.have.lengthOf()
Explanation: .to.have.lengthOf()
is used to assert that an array or string has a specific length.
15.
What does Mocha's before() hook do?
a) Runs
before each test case
b) Runs once before all tests
c) Runs once after all tests
d) Runs after each test case
Answer: b) Runs once before all tests
Explanation: before()
is used for global setup before all tests are run.
16.
Which function can be used to assert that a function throws an error in Chai?
a)
.to.throw()
b) .to.be.true()
c) .to.have.property()
d) .to.equal()
Answer: a) .to.throw()
Explanation: .to.throw()
is used in Chai to assert that a function throws an expected error.
17.
What is the use of done() in an asynchronous test in Mocha?
a) To
indicate that the test is complete
b) To skip a test
c) To check the equality of values
d) To check for errors
Answer: a) To indicate that the test is
complete
Explanation: done()
is called in asynchronous tests to signal that the test is complete.
18.
In Mocha, which method is used to clean up after all tests?
a)
afterEach()
b) before()
c) after()
d) beforeEach()
Answer: c) after()
Explanation: after()
is used to perform cleanup tasks once after all tests have run.
19.
What is the purpose of the .to.be.null assertion in Chai?
a) To
check if a value is true
b) To check if a value is equal to 0
c) To check if a value is null
d) To check if a value is undefined
Answer: c) To check if a value is null
Explanation: .to.be.null
checks if a value is null.
20.
Which of the following is used to check whether an array contains a specific
element?
a)
.to.include()
b) .to.have.property()
c) .to.be.null()
d) .to.equal()
Answer: a) .to.include()
Explanation: .to.include()
is used to check if an array contains a specific element.
21.
How do you test if an array has a specific number of elements in Chai?
a)
.to.have.lengthOf()
b) .to.have.sizeOf()
c) .to.lengthOf()
d) .to.sizeOf()
Answer: a) .to.have.lengthOf()
Explanation: .to.have.lengthOf()
checks if an array has the specified number of elements.
22.
In Mocha, which method is used to run code before every test in the suite?
a)
before()
b) afterEach()
c) beforeEach()
d) after()
Answer: c) beforeEach()
Explanation: beforeEach()
runs before every individual test in the suite.
23.
What happens if an assertion fails in Mocha?
a) The
test passes
b) Mocha moves to the next test
c) Mocha stops executing further tests
d) Mocha logs the failure but continues testing
Answer: c) Mocha stops executing further
tests
Explanation: If an assertion fails, Mocha will
stop executing the current test, but it will proceed with the next tests.
24.
What is the purpose of the describe() function in Mocha?
a) To
assert values in tests
b) To group related tests into a test suite
c) To run an individual test
d) To define the setup logic
Answer: b) To group related tests into a
test suite
Explanation: describe()
is used to group related tests into a suite.
25.
Which of the following is a correct way to import Chai in your test file?
a) const
chai = require('mocha');
b) const chai = require('chai');
c) import chai from 'chai';
d) import { chai } from 'chai';
Answer: b) const chai = require('chai');
Explanation: Chai is imported using require('chai') in Node.js.
26.
Which assertion is used to check if two values are strictly equal in Chai?
a)
.to.equal()
b) .to.eql()
c) .to.be.a()
d) .to.deep.equal()
Answer: a) .to.equal()
Explanation: .to.equal()
checks for strict equality, i.e., both values must be identical.
27.
Which Mocha function is used to run a test only once after all tests in the
suite?
a) beforeEach()
b) after()
c) afterEach()
d) before()
Answer: b) after()
Explanation: after()
runs once after all tests in the suite have finished.
28.
In Chai, how would you check that an array is empty?
a)
.to.be.empty
b) .to.be.null
c) .to.equal([])
d) .to.have.length(0)
Answer: a) .to.be.empty
Explanation: .to.be.empty
checks if an array is empty.
29.
Which Mocha method is used to execute code after each test in the suite?
a)
afterEach()
b) beforeEach()
c) before()
d) after()
Answer: a) afterEach()
Explanation: afterEach()
runs after every individual test in the suite.
30.
What type of function is typically tested using unit tests?
a)
Integration functions
b) Large system components
c) Individual functions and methods
d) User interfaces
Answer: c) Individual functions and methods
Explanation: Unit tests typically test small,
individual functions or methods in isolation.
31.
What does expect(5).to.be.a('number') check in Chai?
a)
Whether the value is 5
b) Whether the value is a number
c) Whether the value is greater than 5
d) Whether the value is a string
Answer: b) Whether the value is a number
Explanation: This assertion checks if the value 5 is of type number.
32.
Which function is used to run tests only in Mocha?
a)
describe()
b) it()
c) run()
d) done()
Answer: b) it()
Explanation: it()
is used to define individual test cases in Mocha.
33.
How do you assert that a function throws an error in Mocha/Chai?
a)
expect(function).to.throw()
b) expect(function).to.throwError()
c) assert.throw()
d) assert.error()
Answer: a) expect(function).to.throw()
Explanation: The correct syntax to check for
errors in Chai is expect(function).to.throw().
34.
What is the role of done() in asynchronous testing?
a) To run
tests sequentially
b) To signal when a test is complete
c) To skip a test
d) To group tests together
Answer: b) To signal when a test is complete
Explanation: done()
is used in asynchronous tests to tell Mocha when the test is complete.
35.
What does describe('Test Suite', function() {...}) do in Mocha?
a)
Defines a group of related tests
b) Runs individual tests
c) Handles asynchronous tests
d) Asserts the output of tests
Answer: a) Defines a group of related tests
Explanation: describe()
is used to group related tests into a suite.
36.
How would you test a promise in Mocha?
a) Use done() for promises
b) Use await with async functions
c) Use expect().to.be.fulfilled()
d) Use callbacks only
Answer: b) Use await
with async
functions
Explanation: Promises can be tested using async/await to handle
asynchronous code.
37.
How would you assert that a function returns a value of true?
a)
expect(value).to.equal(true)
b) expect(value).to.be.true()
c) assert.true(value)
d) all of the above
Answer: d) all of the above
Explanation: All of these assertions correctly
check if a value is true.
38.
How do you ensure a test case runs successfully without throwing errors?
a) Use
the assert
library
b) Ensure the function does not throw any exceptions
c) Always use done()
d) Test the value return
Answer: b) Ensure the function does not
throw any exceptions
Explanation: Tests should check that a function
executes without throwing any unexpected errors.
39.
Which hook is used for one-time setup before all tests run?
a)
beforeEach()
b) before()
c) afterEach()
d) after()
Answer: b) before()
Explanation: before()
is used for one-time setup before any test is run.
40.
In which situation would you use expect().to.be.true?
a) To
check if a number is positive
b) To check if a string matches
c) To check if a boolean is true
d) To check if an object contains properties
Answer: c) To check if a boolean is true
Explanation: This assertion checks if a boolean
value is true.
41.
Which of the following is used to check if an object is empty in Chai?
a)
.to.be.empty
b) .to.equal()
c) .to.have.property()
d) .to.be.null
Answer: a) .to.be.empty
Explanation: .to.be.empty
checks whether an object is empty (has no properties).
42.
How do you handle errors in Mocha tests?
a) Using
the done() function
b) Using try/catch blocks
c) Using asynchronous callbacks
d) All of the above
Answer: d) All of the above
Explanation: Mocha allows handling errors using
the done()
function, try/catch, or asynchronous callbacks.
43.
What does .to.deep.equal() check in Chai?
a) Strict
equality
b) Equality of arrays or objects (deep comparison)
c) Whether two arrays are the same size
d) Whether an object has a property
Answer: b) Equality of arrays or objects
(deep comparison)
Explanation: .to.deep.equal()
checks if the arrays or objects are deeply equal.
44.
What is the role of the afterEach() function in Mocha?
a) To
execute code before each test
b) To clean up after each test
c) To run after all tests
d) To group tests
Answer: b) To clean up after each test
Explanation: afterEach()
is used to run cleanup tasks after each test in the suite.
45.
How do you handle asynchronous code in Mocha without done()?
a) Using
async/await
b) Using promises
c) Using callbacks
d) All of the above
Answer: d) All of the above
Explanation: Mocha supports async/await,
promises, and callbacks to handle asynchronous code.
46.
What is the default behavior of Mocha when an assertion fails?
a) It
stops the test execution immediately
b) It skips the failed test
c) It runs the next test
d) It prints an error and continues with the next test
Answer: a) It stops the test execution
immediately
Explanation: Mocha stops executing the current
test immediately when an assertion fails.
47.
How do you run a single test in Mocha?
a) mocha
testName
b) mocha --single
c) mocha --grep testName
d) mocha run testName
Answer: c) mocha --grep testName
Explanation: The --grep
flag can be used to run specific tests that match a regular expression or name.
48.
Which of the following would you use to test whether a function calls another
function?
a)
Sinon.js
b) Mocha
c) Chai
d) Jest
Answer: a) Sinon.js
Explanation: Sinon.js is used to spy on, mock, or
stub functions in Mocha tests.
49.
What is the Mocha feature that allows for skipping tests?
a)
describe.skip()
b) it.skip()
c) after.skip()
d) before.skip()
Answer: b) it.skip()
Explanation: it.skip()
is used to skip a specific test case in Mocha.
50.
In Chai, which assertion is used to check if a string contains a substring?
a)
.to.include()
b) .to.have.lengthOf()
c) .to.have.property()
d) .to.deep.equal()
Answer: a) .to.include()
Explanation: .to.include()
is used to check if a string contains a given substring.

No comments:
Post a Comment