Skip to content

Commit 05ac5d6

Browse files
committed
Merged branch main into coursework/sprint-3-implement-and-rewrite
2 parents a08e5c7 + c64bb45 commit 05ac5d6

File tree

11 files changed

+217
-105
lines changed

11 files changed

+217
-105
lines changed

Sprint-3/1-implement-and-rewrite-tests/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Implement solutions and rewrite tests with Jest
22

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+
36
## 1 Implement solutions
47

58
In the `implement` directory you've got a number of functions you'll need to implement.

Sprint-3/1-implement-and-rewrite-tests/implement/1-get-angle-type.js

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
// Implement a function getAngleType
2-
// Build up your function case by case, writing tests as you go
3-
// The first test and case is written for you. The next case has a test, but no code.
4-
// Execute this script in your terminal
5-
// node 1-get-angle-type.js
6-
// The assertion error will tell you what the expected output is
7-
// Write the code to pass the test
8-
// Then, write the next test! :) Go through this process until all the cases are implemented
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.
916

1017
function getAngleType(angle) {
1118
if (angle === 180) {
@@ -31,24 +38,17 @@ function getAngleType(angle) {
3138
// This will be useful in the "rewrite tests with jest" step.
3239
module.exports = getAngleType;
3340

34-
// we're going to use this helper function to make our assertions easier to read
35-
// if the actual output matches the target output, the test will pass
41+
// This helper function is written to make our assertions easier to read.
42+
// If the actual output matches the target output, the test will pass
3643
function assertEquals(actualOutput, targetOutput) {
3744
console.assert(
3845
actualOutput === targetOutput,
3946
`Expected ${actualOutput} to equal ${targetOutput}`
4047
);
4148
}
4249

43-
// Acceptance criteria:
44-
45-
// Given an angle in degrees,
46-
// When the function getAngleType is called with this angle,
47-
// Then it should:
48-
49-
// Case 1: Identify Right Angles:
50-
// When the angle is exactly 90 degrees,
51-
// Then the function should return "Right angle"
50+
// TODO: Write tests to cover all cases, including boundary and invalid cases.
51+
// Example: Identify Right Angles
5252
const right = getAngleType(90);
5353
assertEquals(right, "Right angle");
5454

Sprint-3/1-implement-and-rewrite-tests/implement/2-is-proper-fraction.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
// Implement a function isProperFraction
2-
// Write assertions for your function to check it works in different cases
3-
// Terms:
4-
// Fractions: https://www.bbc.co.uk/bitesize/topics/zt9n6g8/articles/zjxpp4j
5-
// Written here like this: 1/2 == Numerator/Denominator
6-
// the first test and first case is written for you
7-
// complete the rest of the tests and cases
8-
// write one test at a time, and make it pass, build your solution up methodically
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.
912

1013
function isProperFraction(numerator, denominator) {
1114
if (numerator < denominator) {
@@ -19,7 +22,7 @@ function isProperFraction(numerator, denominator) {
1922
// This will be useful in the "rewrite tests with jest" step.
2023
module.exports = isProperFraction;
2124

22-
// here's our helper again
25+
// Here's our helper again
2326
function assertEquals(actualOutput, targetOutput) {
2427
console.assert(
2528
actualOutput === targetOutput,

Sprint-3/1-implement-and-rewrite-tests/implement/3-get-card-value.js

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
// This problem involves playing cards: https://en.wikipedia.org/wiki/Standard_52-card_deck
22

3-
// You will need to implement a function getCardValue
4-
// the function takes a single parameter, a string representing a playing card
5-
// the function should return the numerical value of the card
6-
// the first test and first case is written for you
7-
// complete the rest of the tests and cases
8-
// write one test at a time, and make it pass, build your solution up methodically
9-
// just make one change at a time -- don't rush -- programmers are deep and careful thinkers
3+
// Implement a function getCardValue, when given a string representing a playing card,
4+
// should return the numerical value of the card.
5+
6+
// A valid card string will contain a rank followed by the suit.
7+
// The rank can be one of the following strings:
8+
// "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"
9+
// The suit can be one of the following emojis:
10+
// "♠", "♥", "♦", "♣"
11+
// For example: "A♠", "2♥", "10♥", "J♣", "Q♦", "K♦".
12+
13+
// When the card is an ace ("A"), the function should return 11.
14+
// When the card is a face card ("J", "Q", "K"), the function should return 10.
15+
// When the card is a number card ("2" to "10"), the function should return its numeric value.
16+
17+
// When the card string is invalid (not following the above format), the function should
18+
// throw an error.
19+
20+
// Acceptance criteria:
21+
// After you have implemented the function, write tests to cover all the cases, and
22+
// execute the code to ensure all tests pass.
23+
1024
function getCardValue(card) {
1125
const rank = card.slice(0, card.length - 1);
1226
if (rank === "A") {
@@ -24,22 +38,17 @@ function getCardValue(card) {
2438
// This will be useful in the "rewrite tests with jest" step.
2539
module.exports = getCardValue;
2640

27-
// You need to write assertions for your function to check it works in different cases
28-
// we're going to use this helper function to make our assertions easier to read
29-
// if the actual output matches the target output, the test will pass
41+
// Helper functions to make our assertions easier to read.
3042
function assertEquals(actualOutput, targetOutput) {
3143
console.assert(
3244
actualOutput === targetOutput,
3345
`Expected ${actualOutput} to equal ${targetOutput}`
3446
);
3547
}
36-
// Acceptance criteria:
3748

38-
// Given a card string in the format "A♠" (representing a card in blackjack - the last character will always be an emoji for a suit, and all characters before will be a number 2-10, or one letter of J, Q, K, A),
39-
// When the function getCardValue is called with this card string as input,
40-
// Then it should return the numerical card value
41-
const aceofSpades = getCardValue("A♠");
42-
assertEquals(aceofSpades, 11);
49+
// TODO: Write tests to cover all outcomes, including throwing errors for invalid cards.
50+
// Examples:
51+
assertEquals(getCardValue("9♠"), 9);
4352

4453
// Handle Number Cards (2-10):
4554
// Given a card with a rank between "2" and "9",

Sprint-3/1-implement-and-rewrite-tests/rewrite-tests-with-jest/1-get-angle-type.test.js

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,19 @@
22
// We will use the same function, but write tests for it using Jest in this file.
33
const getAngleType = require("../implement/1-get-angle-type");
44

5-
test("should identify right angle (90°)", () => {
6-
expect(getAngleType(90)).toEqual("Right angle");
7-
});
8-
9-
// REPLACE the comments with the tests
10-
// make your test descriptions as clear and readable as possible
11-
12-
// Case 2: Identify Acute Angles:
13-
// When the angle is less than 90 degrees,
14-
// Then the function should return "Acute angle"
5+
// TODO: Write tests in Jest syntax to cover all cases/outcomes,
6+
// including boundary and invalid cases.
157

16-
// Case 3: Identify Obtuse Angles:
17-
// When the angle is greater than 90 degrees and less than 180 degrees,
18-
// Then the function should return "Obtuse angle"
19-
20-
// Case 4: Identify Straight Angles:
21-
// When the angle is exactly 180 degrees,
22-
// Then the function should return "Straight angle"
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+
});
2315

24-
// Case 5: Identify Reflex Angles:
25-
// When the angle is greater than 180 degrees and less than 360 degrees,
26-
// Then the function should return "Reflex angle"
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

Sprint-3/1-implement-and-rewrite-tests/rewrite-tests-with-jest/2-is-proper-fraction.test.js

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@
22
// We will use the same function, but write tests for it using Jest in this file.
33
const isProperFraction = require("../implement/2-is-proper-fraction");
44

5-
test("should return true for a proper fraction", () => {
6-
expect(isProperFraction(2, 3)).toEqual(true);
7-
});
8-
9-
// Case 2: Identify Improper Fractions:
5+
// TODO: Write tests in Jest syntax to cover all combinations of positives, negatives, zeros, and other categories.
106

11-
// Case 3: Identify Negative Fractions:
12-
13-
// Case 4: Identify Equal Numerator and Denominator:
7+
// Special case: numerator is zero
8+
test(`should return false when denominator is zero`, () => {
9+
expect(isProperFraction(1, 0)).toEqual(false);
10+
});

Sprint-3/1-implement-and-rewrite-tests/rewrite-tests-with-jest/3-get-card-value.test.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@
22
// We will use the same function, but write tests for it using Jest in this file.
33
const getCardValue = require("../implement/3-get-card-value");
44

5-
test("should return 11 for Ace of Spades", () => {
6-
const aceofSpades = getCardValue("A♠");
7-
expect(aceofSpades).toEqual(11);
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);
810
});
911

10-
// Case 2: Handle Number Cards (2-10):
11-
// Case 3: Handle Face Cards (J, Q, K):
12-
// Case 4: Handle Ace (A):
13-
// Case 5: Handle Invalid Cards:
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+
- Yields **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.
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
// implement a function countChar that counts the number of times a character occurs in a string
22
const countChar = require("./count");
3-
// Given a string str and a single character char to search for,
3+
// Given a string `str` and a single character `char` to search for,
44
// When the countChar function is called with these inputs,
55
// Then it should:
66

77
// Scenario: Multiple Occurrences
8-
// Given the input string str,
9-
// And a character char that may occur multiple times with overlaps within str (e.g., 'a' in 'aaaaa'),
8+
// Given the input string `str`,
9+
// And a character `char` that occurs one or more times in `str` (e.g., 'a' in 'aaaaa'),
1010
// When the function is called with these inputs,
11-
// Then it should correctly count overlapping occurrences of char (e.g., 'a' appears five times in 'aaaaa').
11+
// Then it should correctly count occurrences of `char`.
1212

1313
test("should count multiple occurrences of a character", () => {
1414
const str = "aaaaa";
@@ -18,7 +18,7 @@ test("should count multiple occurrences of a character", () => {
1818
});
1919

2020
// Scenario: No Occurrences
21-
// Given the input string str,
22-
// And a character char that does not exist within the case-sensitive str,
21+
// Given the input string `str`,
22+
// And a character `char` that does not exist within `str`.
2323
// When the function is called with these inputs,
24-
// Then it should return 0, indicating that no occurrences of the char were found in the case-sensitive str.
24+
// Then it should return 0, indicating that no occurrences of `char` were found.
Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
const getOrdinalNumber = require("./get-ordinal-number");
2-
// In this week's prep, we started implementing getOrdinalNumber
2+
// In this week's prep, we started implementing getOrdinalNumber.
33

4-
// continue testing and implementing getOrdinalNumber for additional cases
5-
// Write your tests using Jest - remember to run your tests often for continual feedback
4+
// Continue testing and implementing getOrdinalNumber for additional cases.
5+
// Write your tests using Jest remember to run your tests often for continual feedback.
66

7-
// Case 1: Identify the ordinal number for 1
8-
// When the number is 1,
9-
// Then the function should return "1st"
7+
// To ensure thorough testing, we need broad scenarios that cover all possible cases.
8+
// Listing individual values, however, can quickly lead to an unmanageable number of test cases.
9+
// Instead of writing tests for individual numbers, consider grouping all possible input values
10+
// into meaningful categories. Then, select representative samples from each category to test.
11+
// This approach improves coverage and makes our tests easier to maintain.
1012

11-
test("should return '1st' for 1", () => {
13+
// Case 1: Numbers ending with 1 (but not 11)
14+
// When the number ends with 1, except those ending with 11,
15+
// Then the function should return a string by appending "st" to the number.
16+
test("should append 'st' for numbers ending with 1, except those ending with 11", () => {
1217
expect(getOrdinalNumber(1)).toEqual("1st");
18+
expect(getOrdinalNumber(21)).toEqual("21st");
19+
expect(getOrdinalNumber(31)).toEqual("131st");
1320
});

0 commit comments

Comments
 (0)