What are you testing?

Bruno Noriller - Jun 5 '22 - - Dev Community

I’m having the privilege of working with people who will be doing testing for the first time.

Meaning… this is an opportunity to observe people who are programming for years, and yet had never tested, be it for “lack of time”, or for not thinking it is important.

Be it as it may… I’ll keep you posted.

What are you testing?

This is probably the first thing I’ve noticed while reviewing the first tests on something that was “already working”.

Code is the law!

If you’re testing something that is “already working”, then that code is the law.

And you should be testing what it is saying it does, and not what you think or what you want it to do.
This might seem contradictory, but if you want your code to do something, then you have to actually have lines of coding that enforce what you want, or else, you’ll end up with something that might just work because of luck.

Example

We started testing an “UserCase”, which is the middle man between the “Controller” and the Repository/Database.

class RepositoryExample {
    async getAll(someFilter){...}
}
Enter fullscreen mode Exit fullscreen mode
class UserCaseExample {
    constructor(repository){
        this.repository = repository;
    }

    validate(someData){...}

    async run(someData){
        if(!validate(someData)){
            // just an example, don't throw plain objects around
            throw {message: '!!!', code: 42};
        }
        return this.repository.getAll(someData);
    }
}
Enter fullscreen mode Exit fullscreen mode
class ControllerExample {
    async getArrayOfSomething(someData){
        const repository = new RepositoryExample();
        const userCase = new UserCaseExample(repository);

        try {
            return userCase.run(someData);
        } catch ({message, code}) {
            HTMLException(message, code);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

I’ve tried to keep it as simple as possible, but what would you test in the UserCaseExample?

The first try

// UserCaseExample.test.js
class MockingRepository {
    constructor(){
        this.database = [...]
    }

    async getAll(someFilter){
        return this.database.filter(...)
    }
}

describe('Testing UserCaseExample', () => {
    it('Valid return of repository data' () => {
        const uc = new UserCaseExample(new MockingRepository());
        const resultArr = uc.run('test');

        expect(resultArr.length > 0 && Array.isArray(resultArr)).toBe(true)
        for (result of resultArr){
            expect(result).toBe(
                expect.objectContaining({
                    key1: expect.stringContaining('test'),
                    key2: expect.any(Number),
                    key3: expect.any(String),
                })
            )
        }
    })
})
Enter fullscreen mode Exit fullscreen mode

While not the scope of this post, there are some wordings that, at least I, find… strange to say the least. This will come later, but feel free to discuss the naming of mock objects, describe blocks, and test names.

Another thing not in scope is the tool you’re using. We are using Jest and the lack of knowledge about mocks, matchers, and how to use Jest API was clear. But knowing the tool is something you’ll have to learn one way or another and each tool will differ. Again, feel free how would you refactor the test above if we ignore the main problem.

The main problem

The intent is clear. They were expecting an array and the test is testing that they are getting the array.

But, you see… the code is law, and in no moment UserCaseExample mention an array.
As is, it simply takes the result from the repository and passes it forward.

This means that the test should only test that whatever you pass in the repository is what you receive back (which could be an array, a null, or a string for all it cares).
You can also test if the filter data is being passed (and you can do it using proper mocks).

If it’s important that you receive an array, then the solution is also clear… change the code to reflect that you want to receive an array.


I’m seeing that this will be the number one thing I’ll keep having to remind people when testing:

What are you testing?

And I’ll keep saying that the code is law, so have the code “tell” you, what you should be testing.
And if you’re testing something that isn’t in the code… then you should change the code first!


Cover Photo by Mufid Majnun on Unsplash

buy me a coffee

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .