Learning Outcome
What did you learn today today
DAMP not DRY in Unit testing:
What is DAMP?
DAMP means Descriptive and Meaningful Phrases. This promotes the readability of your code and increases maintainability by reducing the time necessary to read and understand the code. To understand and maintain a code, you first have to be able to read it.
What is DRY?
DRY means Don’t repeat yourself. This principle promotes the removal or avoidance of duplicates to ensure that every system has a single authoritative representation in the code. DRY increases maintainability by isolating change (risk) to only those parts of the system that must change.
While writing unit test for a Retirement calculator function that checks the working years left before a worker retire’s, and the workers year of retirement, giving their current age, a desired retirement age and the current year. I tended to be more descriptive with variable naming’s as I first defined them before passing them as arguments in the calculator instance.
describe('First scenario', ()=>{
let currentAge = 25;
let desiredRetirementAge = 65;
let currentYear = 2025;
it('calculate working years left of 40', () =>{const calculator = new Calculator(currentAge, desiredRetirementAge, currentYear)
const yearsLeft = calculator.workingYearsLeft() expect(yearsLeft).toEqual(40)
});
it('calculate the year of retirement', () =>{
const calculator = new Calculator(currentAge, desiredRetirementAge, currentYear)
const retirementYear = calculator.retirementYear(calculator.workingYearsLeft(currentAge, desiredRetirementAge)) expect(retirementYear).toEqual(2065) });
})
"DAMP not DRY" values readability over code re-use. The idea of DAMP not DRY in test cases is that tests should be easy to understand, even if that means test cases sometimes have repeated code.
2. Don't use exceptions for non-exceptional conditions.
When testing for edge cases, such as inout validation, I write conditional logics that throws error exceptions with a message when a user supplies a wrong input.
A unit test for a scenario where desiredRetirement age is a string of “65“ instead of an Integer
it('throw error if desiredRetirementAge is not a number', () =>{
expect(() => { new Calculator(20, '65', 2020) }).toThrow()
});
My constructor function
constructor(currentAge, desiredRetirementAge, currentYear = 0){
this.currentAge = currentAge
this.desiredRetirementAge = desiredRetirementAge
this.currentYear = currentYear
if (
!Number.isInteger(currentAge) ||
!Number.isInteger(desiredRetirementAge) ||
!Number.isInteger(currentYear)
)
throw new Error("Invalid, all inputs must be an Integer");
}
Rather than throwing error exceptions, the best thing to do in this case will be to check the incoming input from the user and convert it from a string to an integer. If its a case where the string cannot be converted to an integer,
Example: where the currentAge provided is a string “Twenty’
it('throw error if current age is not a number', () =>{
expect(() => { new Calculator('twenty', 65, 2020) }).toThrow()
});
Rather the best case will be to return an object from the function that contains a status code and message to show the user what the error is
{status: 400, message: “Invalid, all inputs must be an Integer“}