Skip to content

Commit fb10455

Browse files
author
Arthur
committed
finish
1 parent 3f26213 commit fb10455

24 files changed

Lines changed: 636 additions & 0 deletions
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Implement solutions and rewrite tests with Jest
2+
3+
Before writing any code, please read the [Testing Function Guide](testing-guide.md) to learn how
4+
to choose test values that thoroughly test a function.
5+
6+
## 1 Implement solutions
7+
8+
In the `implement` directory you've got a number of functions you'll need to implement.
9+
For each function, you also have a number of different cases you'll need to check for your function.
10+
11+
Write your implementation and your tests to cover the cases the function should fulfil.
12+
13+
Here is a recommended order:
14+
15+
1. `1-get-angle-type.js`
16+
2. `2-is-proper-fraction.js`
17+
3. `3-get-card-value.js`
18+
19+
## 2 Rewrite tests with Jest
20+
21+
`console.log` is most often used as a debugging tool. We use to inspect the state of our program during runtime.
22+
23+
We can use `console.assert` to write assertions: however, it is not very easy to use when writing large test suites. In the first section, Implement, we used a custom "helper function" to make our assertions more readable.
24+
25+
Jest is a whole library of helper functions we can use to make our assertions more readable and easier to write.
26+
27+
Your new task is to write the same tests as you wrote in the `implement` directory, but using Jest instead of `console.assert`.
28+
29+
You shouldn't have to change the contents of `implement` to write these tests.
30+
31+
There are files for your Jest tests in the `rewrite-tests-with-jest` directory. They will automatically use the functions you already implemented.
32+
33+
You can run all the tests in this repo by running `npm test` in your terminal. However, VSCode has a built-in test runner that you can use to run the tests, and this should make it much easier to focus on building up your test cases one at a time.
34+
35+
https://code.visualstudio.com/docs/editor/testing
36+
37+
1. Go to rewrite-tests-with-jest/1-get-angle-type.test.js
38+
2. Click the green play button to run the test. It's on the left of the test function in the gutter.
39+
3. Read the output in the TEST_RESULTS tab at the bottom of the screen.
40+
4. Explore all the tests in this repo by opening the TEST EXPLORER tab. The logo is a beaker.
41+
42+
![VSCode Test Runner](../../run-this-test.png)
43+
44+
![Test Results](../../test-results-output.png)
45+
46+
> [!TIP]
47+
> You can always run a single test file by running `npm test path/to/test-file.test.js`.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Implement a function getAngleType
2+
//
3+
// When given an angle in degrees, it should return a string indicating the type of angle:
4+
// - "Acute angle" for angles greater than 0° and less than 90°
5+
// - "Right angle" for exactly 90°
6+
// - "Obtuse angle" for angles greater than 90° and less than 180°
7+
// - "Straight angle" for exactly 180°
8+
// - "Reflex angle" for angles greater than 180° and less than 360°
9+
// - "Invalid angle" for angles outside the valid range.
10+
11+
// Assumption: The parameter is a valid number. (You do not need to handle non-numeric inputs.)
12+
13+
// Acceptance criteria:
14+
// After you have implemented the function, write tests to cover all the cases, and
15+
// execute the code to ensure all tests pass.
16+
17+
function getAngleType(angle) {
18+
// TODO: Implement this function
19+
}
20+
21+
// The line below allows us to load the getAngleType function into tests in other files.
22+
// This will be useful in the "rewrite tests with jest" step.
23+
module.exports = getAngleType;
24+
25+
// This helper function is written to make our assertions easier to read.
26+
// If the actual output matches the target output, the test will pass
27+
function assertEquals(actualOutput, targetOutput) {
28+
console.assert(
29+
actualOutput === targetOutput,
30+
`Expected ${actualOutput} to equal ${targetOutput}`
31+
);
32+
}
33+
34+
// TODO: Write tests to cover all cases, including boundary and invalid cases.
35+
// Example: Identify Right Angles
36+
const right = getAngleType(90);
37+
assertEquals(right, "Right angle");
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Implement a function isProperFraction,
2+
// when given two numbers, a numerator and a denominator, it should return true if
3+
// the given numbers form a proper fraction, and false otherwise.
4+
5+
// Assumption: The parameters are valid numbers (not NaN or Infinity).
6+
7+
// Note: If you are unfamiliar with proper fractions, please look up its mathematical definition.
8+
9+
// Acceptance criteria:
10+
// After you have implemented the function, write tests to cover all the cases, and
11+
// execute the code to ensure all tests pass.
12+
13+
function isProperFraction(numerator, denominator) {
14+
// TODO: Implement this function
15+
}
16+
17+
// The line below allows us to load the isProperFraction function into tests in other files.
18+
// This will be useful in the "rewrite tests with jest" step.
19+
module.exports = isProperFraction;
20+
21+
// Here's our helper again
22+
function assertEquals(actualOutput, targetOutput) {
23+
console.assert(
24+
actualOutput === targetOutput,
25+
`Expected ${actualOutput} to equal ${targetOutput}`
26+
);
27+
}
28+
29+
// TODO: Write tests to cover all cases.
30+
// What combinations of numerators and denominators should you test?
31+
32+
// Example: 1/2 is a proper fraction
33+
assertEquals(isProperFraction(1, 2), true);
34+
assertEquals(isProperFraction(2, 1), false);
35+
assertEquals(isProperFraction(2, 2), false);
36+
37+
38+
assertEquals(isProperFraction(0, 2), true);
39+
40+
41+
42+
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/// Implement a function getCardValue, when given a string representing a playing card,
2+
// should return the numerical value of the card.
3+
4+
// A valid card string will contain a rank followed by the suit.
5+
// The rank can be one of the following strings:
6+
// "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"
7+
// The suit can be one of the following emojis:
8+
// "♠", "♥", "♦", "♣"
9+
// For example: "A♠", "2♥", "10♥", "J♣", "Q♦", "K♦".
10+
11+
// When the card is an ace ("A"), the function should return 11.
12+
// When the card is a face card ("J", "Q", "K"), the function should return 10.
13+
// When the card is a number card ("2" to "10"), the function should return its numeric value.
14+
15+
// When the card string is invalid (not following the above format), the function should
16+
// throw an error.
17+
18+
// Acceptance criteria:
19+
// After you have implemented the function, write tests to cover all the cases, and
20+
// execute the code to ensure all tests pass.
21+
22+
function getCardValue(card) {
23+
const rank = card.slice(0, -1);
24+
25+
26+
27+
if (rank === "A"){
28+
return 11 ;
29+
}
30+
else if (rank === "J" || rank === "Q" || rank === "K"){
31+
return 10 ;
32+
};
33+
34+
35+
const value = Number(rank);
36+
37+
if( value>=2 && value <= 10 ){
38+
return value};
39+
40+
throw new Error("invalid card!");
41+
}
42+
// The line below allows us to load the getCardValue function into tests in other files.
43+
// This will be useful in the "rewrite tests with jest" step.
44+
module.exports = getCardValue;
45+
46+
// Helper functions to make our assertions easier to read.
47+
function assertEquals(actualOutput, targetOutput) {
48+
console.assert(
49+
actualOutput === targetOutput,
50+
`Expected ${actualOutput} to equal ${targetOutput}`
51+
);
52+
}
53+
54+
// TODO: Write tests to cover all outcomes, including throwing errors for invalid cards.
55+
// Examples:
56+
assertEquals(getCardValue("9♥"), 9);
57+
58+
// Handling invalid cards
59+
try {
60+
getCardValue("invalid");
61+
62+
// This line will not be reached if an error is thrown as expected
63+
console.error("Error was not thrown for invalid card 😢");
64+
} catch (e) {
65+
console.log("Error thrown for invalid card 🎉");
66+
}
67+
68+
69+
try {
70+
getCardValue("null");
71+
72+
console.error("Error was not thrown for null card 😢");
73+
} catch (e) {
74+
console.log("Error thrown for invalid card 🎉")
75+
}
76+
77+
try {
78+
getCardValue("0");
79+
80+
console.error("Error was not thrown for 0 card 😢");
81+
} catch (e) {
82+
console.log("Error thrown for invalid card 🎉")
83+
}
84+
// What other invalid card cases can you think of?
85+
86+
87+
88+
89+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// This statement loads the getAngleType function you wrote in the implement directory.
2+
// We will use the same function, but write tests for it using Jest in this file.
3+
const getAngleType = require("../implement/1-get-angle-type");
4+
5+
// TODO: Write tests in Jest syntax to cover all cases/outcomes,
6+
// including boundary and invalid cases.
7+
8+
// Case 1: Acute angles
9+
test(`should return "Acute angle" when (0 < angle < 90)`, () => {
10+
// Test various acute angles, including boundary cases
11+
expect(getAngleType(1)).toEqual("Acute angle");
12+
expect(getAngleType(45)).toEqual("Acute angle");
13+
expect(getAngleType(89)).toEqual("Acute angle");
14+
});
15+
16+
// Case 2: Right angle
17+
// Case 3: Obtuse angles
18+
// Case 4: Straight angle
19+
// Case 5: Reflex angles
20+
// Case 6: Invalid angles
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// This statement loads the isProperFraction function you wrote in the implement directory.
2+
// We will use the same function, but write tests for it using Jest in this file.
3+
const isProperFraction = require("../implement/2-is-proper-fraction");
4+
5+
// TODO: Write tests in Jest syntax to cover all combinations of positives, negatives, zeros, and other categories.
6+
7+
// Special case: numerator is zero
8+
test(`should return false when denominator is zero`, () => {
9+
expect(isProperFraction(1, 0)).toEqual(false);
10+
});
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// This statement loads the getCardValue function you wrote in the implement directory.
2+
// We will use the same function, but write tests for it using Jest in this file.
3+
const getCardValue = require("../implement/3-get-card-value");
4+
5+
// TODO: Write tests in Jest syntax to cover all possible outcomes.
6+
7+
// Case 1: Ace (A)
8+
test(`Should return 11 when given an ace card`, () => {
9+
expect(getCardValue("A♠")).toEqual(11);
10+
});
11+
12+
// Suggestion: Group the remaining test data into these categories:
13+
// Number Cards (2-10)
14+
// Face Cards (J, Q, K)
15+
// Invalid Cards
16+
17+
// To learn how to test whether a function throws an error as expected in Jest,
18+
// please refer to the Jest documentation:
19+
// https://jestjs.io/docs/expect#tothrowerror
20+
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# A Beginner's Guide to Testing Functions
2+
3+
## 1. What Is a Function?
4+
5+
```
6+
Input ──▶ Function ──▶ Output
7+
```
8+
9+
A function
10+
- Takes **input** (via **arguments**)
11+
- Does some work
12+
- Produces **one output** (via a **return value**)
13+
14+
Example:
15+
16+
```
17+
sum(2, 3) → 5
18+
```
19+
20+
Important idea: the same input should produce the same output.
21+
22+
23+
## 2. Testing Means Predicting
24+
25+
Testing means:
26+
> If I give this input, what output should I get?
27+
28+
29+
## 3. Choosing Good Test Values
30+
31+
### Step 1: Determining the space of possible inputs
32+
Ask:
33+
- What type of value is expected?
34+
- What values make sense?
35+
- If they are numbers:
36+
- Are they integers or floating-point numbers?
37+
- What is their range?
38+
- If they are strings:
39+
- What are their length and patterns?
40+
- What values would not make sense?
41+
42+
### Step 2: Choosing Good Test Values
43+
44+
#### Normal Cases
45+
46+
These confirm that the function works in normal use.
47+
48+
- What does a typical, ordinary input look like?
49+
- Are there multiple ordinary groups of inputs? e.g. for an age checking function, maybe there are "adults" and "children" as expected ordinary groups of inputs.
50+
51+
52+
#### Boundary Cases
53+
54+
Test values exactly at, just inside, and just outside defined ranges.
55+
These values are where logic breaks most often.
56+
57+
#### Consider All Outcomes
58+
59+
Every outcome must be reached by at least one test.
60+
61+
- How many different results can this function produce?
62+
- Have I tested a value that leads to each one?
63+
64+
#### Crossing the Edges and Invalid Values
65+
66+
This tests how the function behaves when assumptions are violated.
67+
- What happens when input is outside of the expected range?
68+
- What happens when input is not of the expected type?
69+
- What happens when input is not in the expected format?
70+
71+
## 4. How to Test
72+
73+
### 1. Using `console.assert()`
74+
75+
```javascript
76+
// Report a failure only when the first argument is false
77+
console.assert( sum(4, 6) === 10, "Expected 4 + 6 to equal 10" );
78+
```
79+
80+
It is simpler than using `if-else` and requires no setup.
81+
82+
### 2. Jest Testing Framework
83+
84+
```javascript
85+
test("Should correctly return the sum of two positive numbers", () => {
86+
expect( sum(4, 6) ).toEqual(10);
87+
... // Can test multiple samples
88+
});
89+
90+
```
91+
92+
Jest supports many useful functions for testing but requires additional setup.

Sprint-3/2-practice-tdd/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Practice TDD
2+
3+
In this section you'll practice this key skill of building up your program test first.
4+
5+
Use the Jest syntax and complete the provided files, meeting the acceptance criteria for each function. Use the VSCode test runner to run your tests and check your progress.
6+
7+
Write the tests _before_ the code that will make them pass.
8+
9+
Recommended order:
10+
11+
1. `count.test.js`
12+
1. `repeat-str.test.js`
13+
1. `get-ordinal-number.test.js`

Sprint-3/2-practice-tdd/count.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
function countChar(stringOfCharacters, findCharacter) {
2+
return 5
3+
}
4+
5+
module.exports = countChar;

0 commit comments

Comments
 (0)