tags:

views:

191

answers:

11

I understand the concept of Unit Testing as coming up with simple ideas about what your code should output - then outputting it. So it's thinking about what you want a piece of code to do - then making a test to ensure it works.

At which point in learning programming should TDD (unit testing) be incorporated?

Edit: I liked the comment about unit testing as soon as the tools to do it stop becoming magical.

Originally the question came about because I realize I don't have the skills yet to develop a large program, but would like to learn by coming up with ideas for what some piece of code could / should do.

I'm wanting to get into learning by doing and I figure a structured way to do this would help. Python is the language I'm using. Thanks for all the input thus far.

+4  A: 

As early as possible. All my hurdles in adopting TDD have been because I've had to break old habits, and change my way of thinking. If I could have thought in terms of TDD from the start I would have found the whole thing much easier.

Matthew Vines
+1 Excellent point.
Mark Brittingham
+1  A: 

Are we talking total novice or programmer who learns new language? If the latter - I would say, right away. Why? Since the best way to learn is to code, and if you code you should test. However someone who has no notion of programming should probably learn the basics of programming first

DroidIn.net
+3  A: 

Unit testing is a huge time saver when you're starting out, because you end up doing a lot of "code, run, debug" cycles while learning. It's that "run" phase that becomes a time suck when you're doing it ad-hoc every time. Also I think beginners tend to introduce more regression problems, which is another huge time sink if you don't catch them right away with a unit test.

dacc
+1 - Great point. This is especially true in web development or in systems that require a login/password and some navigation to get to the code to be tested. It is MUCH easier to write the test and then (in my case) simply right-click the test and tell it to exercise the code you are writing. This is a HUGE boon and one that doesn't get enough recognition in the discussion of TDD.
Mark Brittingham
+1  A: 

Hi there.

TDD makes you think a lot more before coding - something I used to lack in the beginning of my career. I used to get up and running in the IDE and start typing away - code and fix as they say.

If I had used unit testing and TDD earlier in my development as a programmer, then I firmly believe I could have produced better quality code sooner (Not that my code at that time was total crap mind :)

Cheers. Jas.

Jason Evans
+1 - Good point.
Mark Brittingham
+1  A: 

Of course that is a very subjective question, but I think we can certainly put an early limit on it. I would say not before the operations of the unit testing framework stop seeming like magic. So in Java, with JUnit, you need to first understand Exceptions, methods, return values, parameters, basic operators, things like that.

Part of the problem is that a lot of simple programming examples ask for user input, which is hard to unit test, so you don't want to make that too much of a hurdle early on, but if unit testing was commonly done early, then it might be made easier to unit test code that needs to do this.

Yishai
A: 

I think the paradigm (shift in thinking) needed to work with TDD (or want to work with TDD) is that it's justfied by a "holistic" view of where programmers spend time and add value. Pure agile/scrum practioners are trained to see that a piece of code has positive value (and counted as "done") only when it's correctly achieves its goal (of transforming something, etc.). This is because we are only fooling ourselves about value (acceptability) unless it's correct.

Defining the test structure first defines the goal of the coding and where it can go wrong (the edge & negative test cases). Additionally, checking for whether the goal is achieved is automated.

Wilson Mar
A: 

Testing in general should be taught as part of a first course in programming, IMO. Unit testing isn't necessarily something I'd put near the beginning as the idea of what is or isn't a "unit" can easily become about semantics and philosophy. Specifying types of tests as unit tests I could see in a second or third course. Of course I don't remember learning unit testing in university so somehow it didn't get into the curriculum where I went to school back in the '90s.

TDD as a philosophy could probably be used shortly after getting the basic ideas of testing. I'm not sure I'd want to go through all the different kinds of tests with people who have no idea what code looks like. Once someone got a few basics of programming, then tests become a useful way to show that, "Yes, this program does do what it has to do." Students trying out TDD may see it as something easy and natural if they are still relatively new to programming whereas those that have programmed for years may have a hard time adjusting to the paradigm.

JB King
+1  A: 

As a sidenote, TDD and/or unit testing can come very late in the learning process. Even seasoned programmers can gain from Learning Tests when starting working with a new language, or a new API.

Kent Beck recommends this under the "Learning test" name in its "Red bar patterns" in Test-Driven Development: by example.

Instead of just using a new method or a new class, we write a little test that verifies that the API works as expected.

Likewise, Mike Clark wrote a suite of 400+ tests while learning Ruby.

Writing learning tests is a fun way to poke and prod any new language or API. And with every test you write you're investing in an executable knowledge base.

philippe
Oh! What a cool concept. It's like keeping a journal of what you've learned, but an executable journal.
jcdyer
A: 

I guess your concept of Unit Testing is not correct. Technically speaking, "Unit Testing" is a software verification and validation method in which a programmer tests if individual units of source code are fit for use. A unit is the smallest testable part of an application. In procedural programming a unit may be an individual function or procedure and in Object Oriented Programming it may be a method of a class.

What you want to do is basically "doing smaller programs first and then making them complex gradually (and in the course you will learn the programming eventually)". This type of software development "start with simpler and then make it complex gradually" is called "Software Prototyping" technically. Here is a definition of it:

"Software prototyping, an activity during certain software development, is the creation of prototypes, i.e., incomplete versions of the software program being developed. A prototype typically simulates only a few aspects of the features of the eventual program, and may be completely different from the eventual implementation. The conventional purpose of a prototype is to allow users of the software to evaluate developers' proposals for the design of the eventual product by actually trying them out, rather than having to interpret and evaluate the design based on descriptions. Prototyping can also be used by end users to describe and prove requirements that developers have not considered, so "controlling the prototype" can be a key factor in the commercial relationship between solution providers and their clients."

On the other hand, Unit Testing is a just one of the methodology in "Software Testing". It is not a part of Software Development beginning. It is done at the end when fairly large program has been created and to ensure every piece (ie. smaller units like functions, procedures, class methods etc.) are working correctly. Unit Testing can not be used to base a software development because at the end if Unit Testing results into "any one piece has error" it certainly means the whole software is erroneous while if Unit Testing says "all pieces have no error, it doesn't mean that whole software is error free" because there may be some error in integrating those pieces or Unit Testing cannot be expected to catch every error in the program: it is impossible to evaluate every execution path in all but the most trivial programs. The same is true for unit testing. Additionally, unit testing by definition only tests the functionality of the units themselves. Therefore, it will not catch integration errors or broader system-level errors (such as functions performed across multiple units, or non-functional test areas such as performance). Unit testing must be done in conjunction with other software testing activities. Like all forms of software testing, unit tests can only show the presence of errors; they cannot show the absence of errors.

To obtain the intended benefits from unit testing, rigorous discipline is needed throughout the software development process. It is essential to keep careful records not only of the tests that have been performed, but also of all changes that have been made to the source code of this or any other unit in the software. Use of a version control system is essential. If a later version of the unit fails a particular test that it had previously passed, the version-control software can provide a list of the source code changes (if any) that have been applied to the unit since that time.

It is also essential to implement a sustainable process for ensuring that test case failures are reviewed daily and addressed immediately. If such a process is not implemented and ingrained into the team's workflow, the application will evolve out of sync with the unit test suite, increasing false positives and reducing the effectiveness of the test suite.

I hope now you have better understanding of the term "Unit Testing". And what you want to do is learn by "software prototyping". Well, as far as learning is concerned you can opt any way ie. a) Read a lot of programs before you code one b) Just read few basics of any programming language and start creating simpler programs and later on make them complex with your increased knowledge.

Option (a) takes less time to get you on the expert's way and also there is a less chance to adopt wrong practices that you may develop during "Self learning programming"

Option (b) takes more time to get you on the expert's way but may be you may devise your own style of programming and may be it becomes as good as (if not better) other expert's style of programming.

I RECOMMEND DON'T CHOOSE ONLY ONE WAY of the above mentioned options (a) or (b). USE A MIX OF BOTH AND START WITH OPTION (a).

Happy Programming! Welcome to the Crazy Community!

You get a point for effort which I took away for being wrong - I don't think I've ever seen ANYONE assert that unit testing "is done at the end".
Andy Dent
the word "end" may mean "at the end of software" to some developers or it may mean "at the end of the piece or module" for others. Whatever meaning you go with, it always mean software TESTING is always done WHEN there is something DEVELOPED. The guy who asked this question has some misunderstanding of the fact that Unit Testing is a method of Learning by doing while software development books have a different meaning of this term "Unit Testing".
Unit Testing is different from software prototyping. what Brian wants to do is software prototyping... do learn from mistakes... improve... do ... improve ....do ... improve ... until you get what you desired. This thing is not called Unit testing, it is called software prototyping. please feel free to check wikipedia if you haven't read any book on software development yet.
A: 

I think doing unit testing is more about learning good design practices rather than programming in general. What I have found is that when you write your unit tests concurrently you tend to design better components with cleaner interfaces between them.

Igor Zevaka
A: 

Especially considering the context - Python unit tests are very easy to write and require very little understanding - I'd say go for it and blanket your understanding and explorations with tests.

After you have been doing this for a while, include a review stage where you go back and read your earlier tests and see how you would have rewritten them with your current understanding. That's what comments are for - write questions and review notes to yourself in the docstrings inside each test definition.

With such an incremental approach, using version control will help with reviewing and I recommend it highly, in particular because you will be able to see a history of your changes from the version control logs and thus more self-encouragement with your visible progress. I recommend git and using either the built-in gitgui or GitX on Macinosh.

As a very experienced professional, I predate the unit testing concept but I've certainly used lots of small tests as a way to learn new libraries and languages.

Andy Dent