Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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?

share|improve this question
2  
Aren't there mocking-frameworks in C#? This should solve your problems. –  user43552 Feb 20 '12 at 7:09
2  
@user43552: That would just be testing a mock... this scenario is intended to test the audio player. –  Steve Evers Feb 20 '12 at 7:35
5  
I'm not familiar with how to do audio in C#, but it seems to me that you need to refactor this class so that you can inject a mock in place of audioFile.SoundPlayer. Then test with this mock, and verify that PlaySync and Dispose are called at the right places. You also want to be able to inject the StartedPlayingHandler and the StoppedPlayingHandler if possible. –  David Wallace Feb 20 '12 at 7:49
2  
Shouldn't this be on stackoverflow? –  Amr H. Abdel Majeed Feb 20 '12 at 11:15
1  
@AmrH.AbdelMajeed - why? Just because it has code? –  ChrisF Feb 20 '12 at 13:56

2 Answers 2

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.

share|improve this answer
    
+1 for 'There are many things "on the edges" of most systems that cannot adequately be unit tested.' –  user23157 Feb 20 '12 at 9:24
    
This answer is highly misleading. Just because the final output device for audio code is often a pair of speakers, it doesn't mean that audio code cannot be unit tested or that it needs to be tested perceptually. All audio software has a digital output that can be measured and compared to an expected output. One approach to unit testing audio can be found in this paper –  Jamie Bullock Nov 10 at 10:26

It's obviously difficult to automatically test that the audioplayer really plays audio, but you can create useful unit tests anyway. For example, you can test that StartPlaying() causes the StartedPlaying event, and StopPlaying() causes the StoppedPlaying event. You can test the behavour when trying to play an empty playlist, or a null playlist. You can test that AddFile really adds the file to the playlist. You can test that after playing an audio file, it is removed from the playlist (if that is desired). Maybe there are cornercases for broken audio files etc. too that deserve testing.

Having unit tests for those things, you can be sure that the class behaves well, i.e. meets its contracts. If it does, but still plays no sound, that's relatively easy to catch in manual tests.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.