Is TDD a top or bottom design?

In my memory, most people told me that I should design from top to bottom. If I want to embed a web page, I have to put or draw this page on paper, and then divide it into some functionalities. For each functionality, I try to create an external API and implement them inside, respectively.

But in TDD they say that first I have to consider a very small functionality (method?), Write its test, fail, implement it and pass the test. Drawing them up is the last step. I can’t imagine how it gets a good API.

And strangely enough, they say that TDD is not only unit tests, but also functional tests. I think that means a bottom. If there is a functionality A consisting of methods B, C and D. Due to TDD, I first write the test function for A. But ... B, C, D are not all implemented. Should I use three stubs? If B depends on the other three methods?

I used TDD to write small programs. But when I sketched the GUI application, I was stuck.

+4
source share
3 answers

I heavily wrote rspec tests for my rail projects, keeping a ratio between 1: 1.6 between code / tests. I never had a problem with what to write first or what it depends on. If the method A that I want to write consists of B and C, then I must first implement B and C, again using proper testing. For me, consistency is not so important as long as the tests are good and accurate.

So, I really don't use stubs as you describe it, but only if the functionality already exists, and I just want to get around / getting around it.

BTW, this is considered a top-down approach. This is an excerpt from the Rspec book:

If you ask experienced software delivery people why they start the project like this, front-loading it with all the planning and analysis, then going into detailed design and programming, and only really integrating and testing it at the end, they will look into the distance, looking older than their years and patiently explain that this mitigation versus exponential value change is the principle that introducing a change or detecting a defect becomes exponentially more expensive later you discover it. a top-down approach seems to be the only sensible way of hedging the ability to detect a defect at the end of the day.

0
source

Since TDD starts with what you can see from the outside (whatever element you are currently working on), I'm not sure how this can be attributed to the upstream.

Taking TDD to the extreme (for example, like in XP, otherwise extreme programming), you will probably start from the point of view of the end user and only ever write as much code as you need to pass the tests created so far. If you find that you start with tests of some internal function, before you reach the level where tests of a higher level (plus a good design for the code you write to pass these tests) require this procedure, you are working on some other paradigm, not strict TDD - because there was no test telling you to write this method in the first place. Not that this is necessarily bad, but any problems you have with this are not really one of the TDD methodologies.

For GUI programming, of course, you have the standard problem of automating tests, even before creating the code. I know only good tools for web applications; if you have good pointers on this topic in the desktop case, I would really like to see them.

+2
source

I would say that it is from top to bottom. Let's say I had a single PDF in which there were 4 different documents, and I wrote software to separate them into 4 separate documents instead of a single document, the first test I would probably write is the following:

  // Note: Keeping this very abstract
 @Test
 public void splitsDocumentsAccordingToDocumentType () {
    List docs = new DocumentProcessor (). Split (new SinglePdfWithFourDocs ());
    assertEquals (4, docs ());
    ...
 }

I would consider the DocumentProcessor.split() method, which would look like "A" in your example. Now I could implement the whole algorithm in a single split method and skip tests. I don’t even need a “B” or “C”? Knowing that you are a good developer, and you are compressed at the thought of this method of 1500 lines, you will begin to look for ways to rebuild your code to a more suitable design. Perhaps you see that two additional objects (duties) can be divided into this code:

1) Parsing the contents of a file to search for individual documents, and 2) Reading and writing a document from the file system

First, let No. 1 do it. Use a couple of Extract Method refactoring to localize the code associated with the content parsing, and then Extract the Class refactoring by pulling these methods into a class with the name, say DocumentParser . It could be similar to "B" in your example. If you want, you can transfer the tests related to parsing a document from your DocumentProcessorTest to the new DocumentParserTest and run a mock or stub DocumentParser in DocumentProcessorTest .

For # 2, this is pretty much foam, rinse, repeat, and you get something like the DocumentSerializer class, AKA "C". You can mock this also in your DocumentProcessorTest , and now you don’t have file I / O, and it has a component-driven test that has two additional collaborators, without having to design your entire class (using separate methods). Please note that we used the “outside” approach, which really allows refactoring.

thanks

0
source

All Articles