Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do Test Driven Development right way?

Tags:

java

tdd

I have read about TDD and I tried it on my new project.

TDD cycle

I understand that in TDD it is like blackbox testing , ie it matters what rather than how.So, I concluded and stopped testing private methods after reading about it on many posts as it is not correct way.

However, I failed to do it due to these reasons.

I will show you by example : I have a program that reads a text paragraph so I wrote something like this in my test method (for tdd step1).

/*
My program reads a textual paragraph from file and saves it to my custom paragraph object; 
*/

So accordingly I made this method to create the RED case.

public void paragraphMustNotBeNullTest(){
File f = new File("some path")
 ParagraphReader reader= new ParagraphReader();
 reader.read();
assertNotNull("my custom paragraph is null",reader.getCustomParagraph());
}

I have written following code:

package com.olabs.reader;

import java.io.FileInputStream;
import java.io.InputStream;

import com.olabs.models.OlabsParagraph;

public class Para {


    private String paragraphText = null;
    private Paragraph oParagraph = null;

    public Paragraph getCustomParagraph() {
        return oParagraph;
    }
    public void setoParagraph(Paragraph oParagraph) {
        this.oParagraph = oParagraph;
    }

    public void read() {
        InputStream is = new FileInputStream("abc......");
//      ..
        String text = is.read(); // assume I got text read from file.
        this.paragraphText = text;
    }


    private void createCustomParagraph()
    {
        Paragraph p = new Paragraph();
        p.setText(paragraphText);
        p.setId(1);
        p.setType("Story");
        ...........
    }

    private void countWords()
    {
        // counting words in paragraph logic
    }


}

Now the problem is I know beforehand that I will be using countingwords and createCustomParagraph as private methods.

So, in that cases should I go with:

  1. creating them as public and follow tdd cycle.

  2. make them private.

  3. delete the tests for them(as the methods are now private and inaccessible for tests). I think this is quite cumbersome and incorrect way to do tdd.

I am confused about this.Everyone says write code only after you write a failing test, but here if I know I am going to write a private method then how will I do this?

I request you to correct me if I am wrong somewhere. Also if possible give some real example...

Also, I fear that most of the time I will be editing tests or removing them due to access specifiers problems or refactoring ...

Note : This is not a duplicate question. I don't have good answer for realtime situations.In all examples I have seen, they show only a single class with default or public access specifiers, so they really don't show how exactly to work in realtime project.

like image 411
swapyonubuntu Avatar asked Jul 15 '15 18:07

swapyonubuntu


Video Answer


2 Answers

From my personal experience, you are testing the class and the interface to the class by the rest of your application. Your TDD test cases should be written against the public methods of your class. The point is to test that when stimulated, the class outputs the desired results to pass your test criteria. Internal private methods will be tested as a part of the public interface testing, but the goal is to verify that the publicly accessible interface is working. You say you know ahead of time that the private methods will be used, but if someone refactors how things are done in the class without changing the external behavior you will still be able to use your existing tests and verify that refactoring has not broken a previously working method.

like image 92
Brian Kurz Avatar answered Oct 21 '22 17:10

Brian Kurz


If a method is an implementation detail of the primary thing you're building which ought to remain private, that doesn't mean there's no way to write a test for it. You can make that functionality part of another class where it can be public, writing tests that exercise it directly, then call that privately from the primary thing. That way you can test the private methods, no tests get deleted, and you don't have to go through contortions testing something indirectly when the thing using it may not expose access to everything you want to test. And now instead of having private methods that are concealed bits of gnarly code, you have well-tested building blocks ready for reuse somewhere else.

like image 28
Nathan Hughes Avatar answered Oct 21 '22 18:10

Nathan Hughes