DEV Community

loading...

Keeping Javascript test naming updated after refactoring

jankapunkt profile image Jan Küster ・2 min read

Some days ago I ran into a problem. I refactored (simply renamed) some Functions and faced the situation, that I also had to update all the names in my tests, too... manually!

This is because I did not assigned the Functions a proper name, when I created them as a property of something else:

export const Utils = {}

Utils.isDefined = function (obj) {
  return typeof obj !== 'undefined' && obj !== null
}

// ...

In the tests I then wrote the function name by hand:

import { Utils } from '../Utils.js'

describe ('Utils', function () {
  describe ('isDefined', function () {
    // ...
  })
})

Now later I realized, that the name isDefined is somewhat wrong picked and I refactored it to exists:

Utils.exists = function (obj) { 
  return typeof obj !== 'undefined' && obj !== null
}

Well, my tests were not covered by the update and still were outputting the old isDefined:

Utils
  isDefined
    ✓ ...

I was thinking "how could I make my test automatically reflect my Function's namespaces?" and luckily (since ECMA2015) there is a nice way to always get a Function's name, using the name property:

import { Utils } from '../Utils.js'

describe ('Utils', function () {
  describe (Utils.exists.name, function () {
    // ...
  })
})

This will always be the Function's name, because it references to it and is thus covered by the refactoring. Keep in mind however, that in the current state of this code there will be nothing returned as name. This is because the Function simply has no name, yet. To do so we need to declare not only the property but also the Function name:

Utils.exists = function exists (obj) { 
  return typeof obj !== 'undefined' && obj !== null
}

and the tests are then automatically reflecting the naming:

Utils
  exists
    ✓ ...

Simple tweak with a great reduction in follow-up work here. For those of you, who think this would then require to double rename (property and Function name) then I encourage you to try out with your IDE: usually you should just have to refactor-rename one of them to trigger the refactoring of both.

Note, that in order to make this work with arrow functions, you need to declare them as variables:

const exists = (obj) => typeof obj !== 'undefined' && obj !== null
Utils.exists = exists

Discussion

pic
Editor guide