standards-c-sharp

Only test the public interface

Consider the following interface:

public interface IDogTranslator
{
    string ToDog(string input);
}

Don’t

Here, we see the RepeatWord function has been made public and tested separately.

public class DogTranslator : IDogTranslator
{
    public string ToDog(string input)
    {
        return $"{input} {RepeatWord("woof", 3)}";
    }
    
    public static string RepeatWord(string word, int times)
    {
        return String.Join(" ", Enumerable.Repeat(word, times));
    }
}

[TestFixture]
public class DogTranslatorTest
{
    [Test]
    public void TranslateToDog_Woofs()
    {
        var translator = new DogTranslator();
        var result = translator.ToDog("I'm a dog");
        Assert.AreEqual("I'm a dog woof woof woof", result);
    }
    
    [Test]
    public void RepeatWord_Repeats()
    {
        var result = DogTranslator.RepeatWord("meow", 3);
        Assert.AreEqual("meow meow meow", result);
    }
}

Do

RepeatWord is not part of the IDogTranslator interface. It exists only as an implementation detail. We should make it private it and remove its test. It will still be tested, but by calling through the public interface. We are now free to change the implementation without breaking the test.

public class DogTranslator : IDogTranslator
{
    public string ToDog(string input)
    {
        return $"{input} {RepeatWord("woof", 3)}";
    }
    
    private static string RepeatWord(string word, int times)
    {
        return String.Join(" ", Enumerable.Repeat(word, times));
    }
}

[TestFixture]
public class DogTranslatorTest
{
    [Test]
    public void TranslateToDog_Woofs()
    {
        var translator = new DogTranslator();
        var result = translator.ToDog("I'm a dog");
        Assert.AreEqual("I'm a dog woof woof woof", result);
    }
}