DEV Community

Discussion on: Critique my newbie approach to testing

Collapse
 
leightondarkins profile image
Leighton Darkins • Edited

This is a really interesting post, and good on you for seeking feedback!

I'll be very interested to see the responses you get here. Approaches to and opinions on, unit testing are generally wildy variant.

1: This is an example of where laying out expectations for your code, before you write it can be super helpful. I'm not going to start preaching about TDD, but even if you just jot down on a piece of paper what each function should do before you write it, you'll have a great starting point for your test assertions.

Take getBypNick() for example. As I consider that function I'd think to myself:

  • What does it do when:
    • it doesn't receive an argument?
    • it receives a valid argument?
      • that doesn't match a user?
      • that does match a user?
    • What does it do when it receives an invalid argument?
      • What does it do when it receives a number / object / boolean as an argument?

This could go on for a while... but as a result, I walk away with a good set of questions, and expectations that can de translated directly into tests.

Using this approach, I can cover an assumption you've made in your implementation: That you can always call .toLowerCase() on pNick. Right now that would just throw a syntax or type error for number / object / boolean. You can decide for yourself what this function should do in those cases.

2: In general, I just test the public interface of the function. If a function is doing too much, or there are too many assertions covering edge cases in it's internals, I'll extract those internals into separate functions and test them in isolation.

3: You'll run into differing opinions here. Some will say private methods are implementation details that unit tests shouldn't have access to or care about. That would break encapsulation, y'see? Others will say that leaving private methods uncovered is a recipe for disaster. Gotta have that 100% code coverage :P.

Luckily (kind of) in JS "private" functions aren't really a thing (for the time being), so they're always exposed. And given that fact, I generally test "private" functions on JS classes.

It's not breaking encapsulation if it was never encapsulated in the first place ;).

4: This is another source of vastly differing opinions.

I don't like the word "should". To me it implies some amount of variance in the expectation. I like a more binary approach, it either does something, or it doesn't do something.

Most of my it or test blocks look like this:

 it('returns undefined when given a number as an argument, () => {
    expect(thingUnderTest(undefined)).toBeUndefined()
 })
Collapse
 
imthedeveloper profile image
ImTheDeveloper

Excellent response thanks! I've amended a bunch of my test cases now to match your suggestions and it's slowly starting to make more sense to me. As you say there doesn't seem to be much of an approach agreed out there and I've also been reading a number of other posts on dev.to with a similar sentiment, including the misinterpretation of TDD being purely unit testing, when in-fact its an approach to unit testing.