Slides live at https://bit.ly/ujs23-unittesting
The more effort I put into testing the product conceptually at the start of the process, the less effort I [have] to put into manually testing the product at the end because fewer bugs ... emerge as a result.
Trish Khoo, Director of Engineering at Octopus Deploy
A privacy doorknob, when the push button is not pressed, when the user turns the inside knob, should also turn the outside knob.
GIVEN the push button is not pressed
WHEN the user turns the inside knob
THEN the outside knob should also turn
A privacy doorknob, when the push button is not pressed, when the user turns the inside knob, should also turn the outside knob.
A privacy doorknob, when the push button is not pressed, when the user turns the inside knob, should retract the latch bolt.
A privacy doorknob, when the push button is not pressed, when the user turns the inside knob clockwise, should also turn the outside knob counterclockwise.
A privacy doorknob, when the push button is not pressed, when the user turns the inside knob counterclockwise, should also turn the outside knob clockwise.
A privacy doorknob, when the push button is not pressed, when the user turns the outside knob clockwise, should also turn the inside knob counterclockwise.
A privacy doorknob, when the push button is not pressed, when the user turns the outside knob counterclockwise, should also turn the inside knob clockwise.
A privacy doorknob, when the push button is not pressed, when the user turns the outside knob, should retract the latch bolt.
A privacy doorknob, when the push button is not pressed, when the user turns the inside knob clockwise, should also turn the outside knob counterclockwise.
A privacy doorknob, when the push button is not pressed, when the user turns the inside knob counterclockwise, should also turn the outside knob clockwise.
A privacy doorknob, when the push button is not pressed, when the user turns the inside knob, should retract the latch bolt.
A privacy doorknob, when the push button is not pressed, when the user turns the outside knob clockwise, should also turn the inside knob counterclockwise.
A privacy doorknob, when the push button is not pressed, when the user turns the outside knob counterclockwise, should also turn the inside knob clockwise.
A privacy doorknob, when the push button is not pressed, when the user turns the outside knob, should retract the latch bolt.
i.e. DRY
export class PrivacyDoorknob {
private _isButtonPressed = false;
get isButtonPressed(): boolean {
return this._isButtonPressed;
}
pressButton() {
this._isButtonPressed = true;
}
turnOutsideKnob(direction: RotationDirection): IKnobInteractionResult {
if (this._isButtonPressed) {
return {
latchBolt: 'extended',
};
}
return {
insideKnob: opposite(direction),
outsideKnob: direction,
latchBolt: 'retracted',
};
}
turnInsideKnob(direction: RotationDirection): IKnobInteractionResult {
this._isButtonPressed = false;
return {
insideKnob: direction,
outsideKnob: opposite(direction),
latchBolt: 'retracted',
};
}
}
export type RotationDirection = 'clockwise' | 'counterclockwise';
export interface IKnobInteractionResult {
outsideKnob?: RotationDirection;
insideKnob?: RotationDirection;
latchBolt: 'extended' | 'retracted';
}
function opposite(direction: RotationDirection): RotationDirection {
switch (direction) {
case 'clockwise':
return 'counterclockwise';
case 'counterclockwise':
return 'clockwise';
default:
throw new Error(`Invalid direction ${direction}`);
}
}
describe('', () => {});
describe('', () => {
// * A privacy doorknob,
// * when the push button is pressed,
// * when the user tries to turn the outside knob clockwise,
// * should not turn the outside knob at all.
// * should not turn the inside knob at all.
// * should not retract the latch bolt.
// * when the user tries to turn the outside knob counterclockwise,
// * should not turn the outside knob at all.
// * should not turn the inside knob at all.
// * should not retract the latch bolt.
// * when the user tries to turn the inside knob clockwise,
// * should pop the push button out.
// * should turn the inside knob clockwise.
// * should turn the outside knob counterclockwise.
// * should retract the latch bolt.
// * when the user tries to turn the inside knob counterclockwise,
// * should pop the push button out.
// * should turn the inside knob counterclockwise.
// * should turn the outside knob clockwise.
// * should retract the latch bolt.
});
describe('A privacy doorknob', () => {
describe('when the push button is pressed', () => {
describe('when the user tries to turn the outside knob clockwise', () => {
it('should not turn the outside knob at all');
it('should not turn the inside knob at all');
it('should not retract the latch bolt');
});
});
// * when the user tries to turn the outside knob counterclockwise,
// * should not turn the inside knob at all.
// * should not retract the latch bolt.
// * when the user tries to turn the inside knob clockwise,
// * should pop the push button out.
// * should turn the inside knob clockwise.
// * should turn the outside knob counterclockwise.
// * should retract the latch bolt.
// * when the user tries to turn the inside knob counterclockwise,
// * should pop the push button out.
// * should turn the inside knob counterclockwise.
// * should turn the outside knob clockwise.
// * should retract the latch bolt.
});
it('should not turn the outside knob at all', () => {
// Arrange
const knob = new PrivacyDoorKnob();
knob.pressButton();
// Act
const result = knob.turnOutsideKnob('clockwise');
// Assert
expect(result.outsideKnob).not.toBeDefined();
});
it('should not turn the inside knob at all', () => {
// Arrange
const knob = new PrivacyDoorKnob();
knob.pressButton();
// Act
const result = knob.turnOutsideKnob('clockwise');
// Assert
expect(result.insideKnob).not.toBeDefined();
});
it('should not retract the latch bolt', () => {
// Arrange
const knob = new PrivacyDoorKnob();
knob.pressButton();
// Act
const result = knob.turnOutsideKnob('clockwise');
// Assert
expect(result.latchBolt).toBe('extended');
});
describe('A privacy doorknob', () => {
describe('when the push button is pressed', () => {
describe('when the user tries to turn the outside knob clockwise', () => {
it('should not turn the outside knob at all', () => {
// Arrange
const knob = new PrivacyDoorknob();
knob.pressButton();
// Act
const result = knob.turnOutsideKnob('clockwise');
// Assert
expect(result.outsideKnob).not.toBeDefined();
});
it('should not turn the inside knob at all', () => {
// Arrange
const knob = new PrivacyDoorknob();
knob.pressButton();
// Act
const result = knob.turnOutsideKnob('clockwise');
// Assert
expect(result.insideKnob).not.toBeDefined();
});
it('should not retract the latch bolt', () => {
// Arrange
const knob = new PrivacyDoorknob();
knob.pressButton();
// Act
const result = knob.turnOutsideKnob('clockwise');
// Assert
expect(result.latchBolt).toBe('extended');
});
});
});
});
function removeVowels(input: string): string {/* TODO */}
Test:
Contact me:
joe@worldclassengineers.dev