-
-
Notifications
You must be signed in to change notification settings - Fork 273
London | 25-ITP-SEP | Imran Mohamed| Sprint 3 | Coursework/sprint 3 practice tdd #794
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
London | 25-ITP-SEP | Imran Mohamed| Sprint 3 | Coursework/sprint 3 practice tdd #794
Conversation
jennethydyrova
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @i786m! Kudos on writing clean and readable functions! You did a good job with the unit tests as well. However, unit tests are designed to catch bugs from unexpected usage, which is why it's important to pass different types of parameters and test various scenarios. Please make your test cases more thorough to ensure your functions handle edge cases properly.
| // And a character char that does not exist within the case-sensitive str, | ||
| // When the function is called with these inputs, | ||
| // Then it should return 0, indicating that no occurrences of the char were found in the case-sensitive str. | ||
| test("should return 0 if no occurrences of a character", () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These unit tests are good but they are a bit slim. Can you think of corner and edge cases that your function might encounter? What if, for example, other data types or not all parameters are passed? Thinking about these scenarios will make your function more robust and your tests more thorough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| expect(getOrdinalNumber(1)).toEqual("1st"); | ||
| }); | ||
|
|
||
| test("should return '2nd' for 2", () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as my previous comment. What if someone passes "3", undefined, or another unexpected value to your function? I understand your assumptions, but users of your functions (both internal within your team and external if you build some sort of API) can pass values you didn't safeguard against, which can break your function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯
| @@ -21,12 +21,30 @@ test("should repeat the string count times", () => { | |||
| // When the repeat function is called with these inputs, | |||
| // Then it should return the original str without repetition, ensuring that a count of 1 results in no repetition. | |||
|
|
|||
| test("should return original string if count is 1", () => { | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, the test cases are quite limited. If I call your function with something like repeat("hello", "3") or repeat("hello", null), it will work because of javascript's type coercion, but is that the behavior you want? Writing more test cases with different input types will help you catch any behavior that you didn't intentionally design into your function.
…r get ordinal number
|
I have amended the code & tests based on the comments made , pleases let me know if this is sufficient. |
jennethydyrova
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @i786m! Very good job. There are two things I would like you to do before completing this PR.
- Remove console logs.
- Decide between throwing error and returning error string in
repeatfn.
Rest of my comments are optional, just food for thought 🙂
Sprint-3/2-practice-tdd/count.js
Outdated
| if (stringOfCharacters.length === 0) { | ||
| return 0; | ||
| } | ||
| console.log(Array.from(stringOfCharacters)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please remove this console log? This helps to keep PR clean.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have removed console log, will ensure future PRs are free from debugging logs
| if (typeof num !== "number" || isNaN(num)) { | ||
| throw new Error("Input must be a number"); | ||
| } | ||
| if (!Number.isFinite(num)){ | ||
| throw new Error("Input must be a finite number"); | ||
| } | ||
| if (!Number.isInteger(num) || num < 0) { | ||
| throw new Error("Input must be a non-negative integer"); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good validation but I think this could be simplified because at the end your input should be a Non-negative integer. For example, Number.isFinite() and isNan() have some overlap, can you check in the MDN docs?
I am leaving this as an optional comment, no action needs to be taken to complete this PR but I would like you think if this could be written simpler. You do not need to throw different error for each small case, you can have more general error for anything that is negative non-integer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed code taking overlap in consideration
| if ( arguments.length !== 2) { | ||
| return "Function requires exactly 2 arguments"; | ||
| } | ||
| if (typeof str !== "string") { | ||
| return "First argument must be a string"; | ||
| } | ||
| if (!Number.isInteger(count) || count < 0) { | ||
| return "Second argument must be a non-negative integer"; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see you extensively use throw Error in other functions, is there a reason you want to use just return here?
Small point, no action required to complete this PR but you could improve your error messages to be something like throw Error("Second argument must be a non-negative integer, received: ${count} (${typeof count})") (same for str). It would be a bit easier to debug.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed returns to throw errors to match the rest in this sprint
wheresdiasd
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks good overall, @jennethydyrova comments must be addressed IMO.
My comments are only suggestions to improve the code synthax.
Sprint-3/2-practice-tdd/count.js
Outdated
| @@ -1,5 +1,22 @@ | |||
| function countChar(stringOfCharacters, findCharacter) { | |||
| return 5 | |||
| if (arguments.length !== 2) { | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That looks good, but can we be more specific about which arguments we are expecting? Using " arguments" works, but in my experience is not very common.
Sprint-3/2-practice-tdd/count.js
Outdated
| if (findCharacter.length !== 1) { | ||
| throw new Error("Character to find must be a single character."); | ||
| } | ||
| if (stringOfCharacters.length === 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would that be the same as
(!stringOfCharacters.length) ?
| if (typeof stringOfCharacters !== 'string'){ | ||
| throw new Error("First argument must be a string."); | ||
| } | ||
| if (typeof findCharacter !== "string") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we wrap up this condition and the condition above into a single condition ?
Sprint-3/2-practice-tdd/count.js
Outdated
| if (stringOfCharacters.length === 0) { | ||
| return 0; | ||
| } | ||
| return Array.from(stringOfCharacters).filter(char => char === findCharacter).length; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we use spread operator here ? [...stringOfCharacters] ?
| // And a character char that does not exist within the case-sensitive str, | ||
| // When the function is called with these inputs, | ||
| // Then it should return 0, indicating that no occurrences of the char were found in the case-sensitive str. | ||
| test("should return 0 if no occurrences of a character", () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| @@ -1,5 +1,39 @@ | |||
| function getOrdinalNumber(num) { | |||
| return "1st"; | |||
| if (arguments.length !== 1) { | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, can we be more specific about which arguments we are referring to?
| if (!isFinite(num)) { | ||
| throw new Error("Input must be a finite number"); | ||
| } | ||
| if (!Number.isInteger(num) || num < 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we wrap all these conditions in one statement ?
| expect(getOrdinalNumber(1)).toEqual("1st"); | ||
| }); | ||
|
|
||
| test("should return '2nd' for 2", () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯
| function repeat() { | ||
| return "hellohellohello"; | ||
| function repeat(str, count) { | ||
| if ( arguments.length !== 2) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same about the args here, could we be more specific ?
wheresdiasd
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR LGTM as you've addressed @jennethydyrova changes, however, I left suggestions to improve code standards, please let me know if you want to discuss any item, we can book a call/pair programming to do it so.
Thanks.
|
Could you please solve conflicts on your branch before I mark it as completed ? |
…n and error handling
…n and error handling in newly files to reflect upstream changes
|
|
||
| test('should have the correct amount of arguments', () => { | ||
| expect(() => repeatStr('hello')).toThrow(new Error("Function requires exactly two arguments: a string and a count. Received 1 arguments")); | ||
| expect(() => repeatStr("hello", 3, 3)).toThrow(new Error("Function requires exactly two arguments: a string and a count. Received 3 arguments")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need to check if the function receives more than 2 arguments.
We need to check whether the arguments are expected or not.
In this case, you have 2 arguments, and your logic works fine. But that wouldn't be accepted in real use cases.
Ideally, you would first check if the function receives both str and count before proceeding to any other steps, and that would be enough.
In the real world, functions can indeed receive more parameters than they expect, but they don't do anything with these parameters.
wheresdiasd
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic works, but adding a check to see if the function receives more arguments is unrealistic.
|
Removed the test for more than 2 arguments as you've pointed out in your previous comment and I've taken your comments on board |
wheresdiasd
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR looks good, although I would still avoid the checking arguments.length whenever possible.
Self checklist
Changelist
I have implemented tests, and used tdd to implement the functions set out in the coursework.