Roman Numerals: Refactor Tests
Explore techniques for refactoring Go tests, focusing on the Roman numerals example. Learn to replace magic numbers with constants, improve error assertions, apply table-driven tests, and adopt clear naming conventions to write clean and robust tests essential for scalable software development.
We'll cover the following...
Now that we have a working program with valid tests, let’s do some refactoring. We’ll practice the rules for clean tests (and code in general) learned so far. Our starting point is the code below:
package roman_numerals
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestDecimalToRoman(t *testing.T) {
t.Run("Happy_Path_9", func(t *testing.T) {
got, err := DecimalToRoman(9)
assert.Equal(t, "IX", got)
assert.Nil(t, err)
})
t.Run("Happy_Path_45", func(t *testing.T) {
got, err := DecimalToRoman(45)
assert.Equal(t, "XLV", got)
assert.Nil(t, err)
})
t.Run("Happy_Path_99", func(t *testing.T) {
got, err := DecimalToRoman(99)
assert.Equal(t, "XCIX", got)
assert.Nil(t, err)
})
t.Run("Happy_Path_222", func(t *testing.T) {
got, err := DecimalToRoman(222)
assert.Equal(t, "CCXXII", got)
assert.Nil(t, err)
})
t.Run("Happy_Path_1054", func(t *testing.T) {
got, err := DecimalToRoman(1054)
assert.Equal(t, "MLIV", got)
assert.Nil(t, err)
})
t.Run("Happy_Path_3999", func(t *testing.T) {
got, err := DecimalToRoman(3999)
assert.Equal(t, "MMMCMXCIX", got)
assert.Nil(t, err)
})
t.Run("Sad_Path_0", func(t *testing.T) {
got, err := DecimalToRoman(0)
assert.Empty(t, got)
assert.EqualError(t, err, "decimal number has to be from 1 to 3999")
})
t.Run("Sad_Path_4500", func(t *testing.T) {
got, err := DecimalToRoman(4500)
assert.Empty(t, got)
assert.EqualError(t, err, "decimal number has to be from 1 to 3999")
})
}
Let’s see which refactorings we can do in the code above.
Magic numbers
The first refactoring we can do is about magic numbers. In the main.go file, we see that the if construct checks the decimalValue against 1 and 3999. These literals intend to delimit the allowed range for Roman conversion. However, this intent is not explicit in the code. To make it more explicit, we can introduce two constants: ...