C# – How to unit test audio

ctdd

I have inherited a small project and want to extend it and stabilize it at the same time by writing Unit Tests for all the new code I am adding. The first class, TypedAudioCreator, creates audio files and this turned out to be very easy to test first and write code for second.

However, when it came time to write TypedAudioPlayer, I had no idea how I could test it. It's a very small class focusing on the very basics of playing sound:

public class TypedAudioFilePlayer
{
    public event StartedPlayingHandler StartedPlaying;
    public event StoppedPlayingHandler StoppedPlaying;

    public readonly int TimeBetweenPlays;

    private Queue<TypedAudioFile> _playlist = new Queue<TypedAudioFile>(); 

    public TypedAudioFilePlayer(int timeBetweenPlays)
    {
        TimeBetweenPlays = timeBetweenPlays;
    }

    public void AddFile(TypedAudioFile file)
    {
        _playlist.Enqueue(file);
    }

    public void StartPlaying()
    {
        ThreadPool.QueueUserWorkItem(ignoredState =>
        {
            while (_playlist.Count > 0)
            {
                var audioFile = _playlist.Dequeue();

                if (StartedPlaying != null)
                    StartedPlaying(audioFile);

                audioFile.SoundPlayer.PlaySync();
                audioFile.SoundPlayer.Dispose();

                if (StoppedPlaying != null)
                    StoppedPlaying(audioFile);
            }
        });
    }

    public void StopPlaying()
    {
        if (StoppedPlaying != null)
            StoppedPlaying(null);
    }
}

I'm still very new at TDD, but I realize the benefits of the practice and would like to try and get better at it. I have written Code first, no tests here, but that was just me being too lazy to properly think of the TDD way of solving it. The question I have is, how should/could I test this class?

Best Answer

There are many things "on the edges" of most systems that cannot adequately be unit tested. For example, anything that produces graphics or sound. For these kinds of systems, you are probably best off with manual testing. Even given an automated solution, these outputs are meant for human perception. The only way to know that you are producing the desired effect is to have a human interact with them.

It may be possible to perform a manual test, then record the output of that manual test and create an automated test that ensures that the output does not change. Be warned though that tests like these are incredibly fragile: any change to the underlying code may require a repeat of the manual test and then creating a new recording for the automated test.