TDD from peephole

TDD from peephole

Photo by Goran Ivos on Unsplash

TDD(Test Driven Development) is AWESOME. TDD a.k.a red-green-refactor is a software development approach where you first write your test (specification) for your program. The test must specify all the behavior that you expect from your component or class or program. Run the test and just DON’T PANIC. As the name suggests it’s RED which means lots of error.

Now in the second phase - GREEN phase, you turn all your reds (error) to greens (error-free code). You actually write behavior of your program in this step. REMEMBER that you cannot directly run your program, you need to validate your program behavior using Test only. So for each modification in your program, you run your test file. This ensures that you fulfill your test cases.

Now the final step -REFACTOR, where you manage your spaghetti code. This is an IMPORTANT phase where you get a chance to improve your codebase readability and maintainability. The motivation here is that your program requirements may change later, so if you don’t refactor then GOOD LUCK fixing your code LATER. Some companies also have implemented strict policies regarding this.

The main core advantages of TDD, I found to my knowledge and experience are:

  • You are adding tests, hence contributing directly to Quality of Software/Program.

  • You are somewhat providing documentation for your program.

  • You improve codebase.

  • You can easily automate the test process for faster development.

  • Your program could have affected other program so, this can be traced as quickly as possible.

  • You gradually overcome the error PHOBIA. You develop a habit of reading error messages.

USING TDD

Enough of TDD talks let’s implement it. (SPOILER ALERT: section below involves codes)

To demonstrate, I have used **Ruby Programming language. I will be using [Rspec ](rspec.info/)**to test my ruby program. If you are new to Ruby or RSpec, WORRY NOT you will find them very similar to English. For installation

Consider a Requirement

**Write a class for a Jukebox with attribute songs. Embed methods to play current song, next song, shuffle song, add songs.**

songs = [“song1.mp3”, “song2.mp3”,”song3.mp3”]

jukebox = Jukebox.new(songs)

jukebox.play

#=> “song1.mp3”

jukebox.next

#=> “song2.mp3”

jukebox.previous

#=> “song1.mp3”

jukebox.shuffle

#=> “song2.mp3”

jukebox.add_song(“songs4.mp3”)

#=> [“song1.mp3”, “song2.mp3”,”song3.mp3”, “song4.mp3”]

So Now let’s start with a test file which states all behavior of given requirements. Convention for naming test file for a rubyfile ruby_fileis ruby_file + _spec.rb . So I have prepared specfile for this program as

#juke_box_spec.rb
require '**juke_box**'

describe **JukeBox** do 
    let(:songs) {['song1.mp3','song2.mp3','song3.mp3']}

    describe '**.play**' do
        subject {JukeBox.new(songs).play}

        it 'should return current song' do
            expect(subject).to eq('song1.mp3')
        end 
    end

    describe '.next' do
        subject {JukeBox.new(songs).next}

        it 'should return next song' do
            expect(subject).to eq('song2.mp3')
        end 
    end

    describe '.previous' do 
        subject {JukeBox.new(songs).previous}

        it 'should return previous song' do
            expect(subject).to eq('song3.mp3')
        end 
    end

    describe '.add_song' do
        subject {JukeBox.new(songs).add_song(new_song)}
        let(:new_song) {'song4.mp3'}

        it 'should return new songs list' do
            expect(subject).to match_array(songs.push(new_song))
        end 
    end

    describe '.shuffle' do
        subject {JukeBox.new(songs).shuffle}
        let(:previous_first_song){'song1.mp3'}

        it 'should not return previous songs order list' do
            expect(subject).not_to eq(previous_first_song)
        end 
    end
end

Now we run this test file with the command rspec juke_box_spec.rb``.The first error message we get is the filejuke_box.rb not found so let’s create a file namedjuke_box.rb, run test again we get an error messageNoMethodError``, so specify methods in your program. Again run the test you will get another error fix it and continue this process until you create your program file similar to mine. And also don’t forget to REFACTOR!

#juke_box.rb

class JukeBox 
   #define constructor
    def initialize(songs_list)
       #create instance variable songs and current_song
       @songs=songs_list
       @current_song=0
    end

    def play
        #Last line is returned by default in ruby function
        @songs[@current_song]
    end

    def next
        @current_song=(@current_song+1)% @songs.length
        play
    end

    def previous
        @current_song<=0 ? @current_song=@songs.length-1 : @current_song-=1
        play
    end

    def shuffle
        @songs.shuffle!
        #Optional to set  current song to first song
        @current_song=0
        play 
    end

    def add_song(new_song)
        #Push new song to songs array
        @songs << new_song
    end
end