I have been wrestling with this question for far too long now. I know I need to just jump into one or the other since they are both obviously viable/useful tools, but have been stuck on the fence, researching both, for weeks.
PHPUnit vs. PHPSpec - Which one may lead to better long-term maintainability and programming practices?
I have talked to several seasoned PHPUnit -> PHPspec converts/users who now swear by PHPspec, claiming that it promotes better design thanks to its BDD approach. However, since it is a much newer tool there is a lack of community/tutorials in comparison with PHPUnit.
Currently, my PHP development is focused around Laravel 4 development.
Where PHPUnit is basically baked into the Laravel framework, it seems like that may be the easier choice up front, but I really like the BDD aspect of PHPSpec. However, it seems that PHPSpec doesn't want to play nicely with Laravel's facade setup (which I'm also finding may be a good practice to steer clear of when possible).
My real conundrum is which of these will be more likely to be successfully integrated into an existing Laravel 4 project with zero existing test coverage.
I had an early/brief stab at integrating both PHPUnit and PHPSpec into an existing project, but really just wasn't sure where to begin with writing the initial tests and ended up scrapping them for the time being.
I am really trying to sort out which one may be more worth investing some time into in the long run.
Any resources/insight from anyone who has experienced both would be greatly appreciated.
PhpSpec
PhpSpec is a design tool. It will make your life hard in the beginning if you're not used to TDD (test-first approach).
You'll learn a lot during the process though. You will also swear a lot. Many things, which are considered a bad practice, are not possible with PhpSpec (like partial mocks for example). You'll have to understand it and embrace it. Testing Laravel's facade's is hard, 'cause that's not OOP.
It's much harder to test an existing code with PhpSpec, since you have to make it testable first (which is easier with a test-first approach).
PhpUnit
On the other hand, PhpUnit is a testing tool. You can use it with TDD, BDD or whatever you call it. But you don't have to.
Choice
If your aim is to learn how to design better and you're commited to test-first approach, PhpSpec will help you. If your aim is to test or verify, PhpUnit is your friend.
TDD vs BDD
It's not either TDD or BDD. At least from a code level perspective, they're the same. BDD started as a TDD-redefined, offering a better terminology. Now it goes beyond the code level and it's so much more than that. These days I prefer to use a term proposed by Gojko Adzic - Specification by Example.
Related
Chapter about TDD from Martin's "Clean Code" caught my imagination.
However.
These days I am mostly expanding or fixing large existing apps.
TDD, on the other hand, seems to only be working only for writing from scratch.
Talking about these large existing apps:
1. they were not writted with TDD (of course).
2. I cannot rewrite them.
3. writing comprehensive TDD-style tests for them is out of question in the timeframe.
I have not seen any mention of TDD "bootstrap" into large monolite existing app.
The problem is that most classes of these apps, in principle, work only inside the app.
They are not separable. They are not generic. Just to fire them up, you need half of the whole app, at least. Everything is connected to everything.
So, where is the bootstrap ?
Or there is alternative technique with results of TDD
that'd work for expanding the existing apps that were not developed with TDD ?
The bootstrap is to isolate the area you're working on and add tests for behavior you want to preserve and behavior you want to add. The hard part of course is making it possible, as untested code tends to be tangled together in ways that make it difficult to isolate an area of code to make it testable.
Buy Working Effectively with Legacy Code, which gives plenty of guidance on how to do exactly what you're aiming for.
You might also want to look at the answers to this related question, Adding unit tests to legacy code.
Start small. Grab a section of code that can reasonably be extracted and made into a testable class, and do it. If the application is riddled with so many hard dependencies and terrifying spaghetti logic that you can't possibly refactor without fear of breaking something, start by making a bunch of integration tests, just so you can confirm proper behavior before/after you start messing around with it.
Your existing application sounds as if it suffers from tight coupling and a large amount of technical debt. In cases such as these you can spend a LOT of time trying to write comprehensive unit tests where time may be better spent doing major refactoring, specifically promoting loose coupling.
In other cases investing time and effort into unit testing with Mocking frameworks can be beneficial as it helps decouple the application for purposes of testing, making it possible to test single components. Dependency Injection techniques can be used in conjunction with mocking to help make this happen as well.
In my shop, there isn't much familiarity with unit testing in general, but I'd like to get into it, at the very least, as a proof of concept. Would it be a crazy idea to simply use the Visual Studio function Create Unit Tests on my small (~500 lines) code base and show the concept that way?
Not a crazy idea at all, just know what you should expect to get from that approach.
If you just want to show how to unit test existing code, which is what Roy Osherove calls TAD (Test After Development), it is a quick and easy way to show what kind of things should be tested.
If you are unit testing because you are interested in moving towards TDD, then your approach may serve to confuse, rather than enlighten. Trying to show someone TDD by adding unit tests to existing code defeats the purpose, in my opinion.
Rather, I would look into something (like SpecFlow) that attempts to focus on the spirit of TDD, which is that you're writing a specification (or requirement) in your test code, before you write the real code to make it work.
A light switch flipped for me when I realized that a unit test written before code could actually be my very detailed requirement. It was self-documenting, and as long as the unit test (spec) was written correctly, then my working code was guaranteed to meet the requirement!
If you agree with this, you may want to take a look at the Bowling Game Kata. I found it very helpful for introducing unit testing and TDD concepts.
No this is not crazy at all and is IMHO a great idea.
The only way a group or company can get into a culture of Unit Testing is if someone starts using it. If you don't it's unlikely that the existing people who aren't familiar with the concept will.
A potentially even better idea would be to grab a couple bugs on your plate and write the unit tests which reproduce the failure. Demo the tests catching the real bug and validating the solution. I find that's often fairly compelling for people who aren't familiar with the concept of unit testing.
My question is same as the title. I have not done Test driven development yet,I have performed unit testing and I am aware of testing in general but I hear it is much advantageous to follow TDD?. So should I opt for it everytime or are there some preconditions... i just need to know some basic or important requirements when i should opt for TDD. Sorry if this question is too trivial.
I would say whenever you are coding for a project. By this I mean where you are hoping to produce code that will be used by people. This is basically all code apart from research where you are learning and discovering new techniques.
Even if you think the project is just a small one often things spiral up out of control without care. You wil be glad for the tests when you find yourself having to refactor a big sprawl of code.
Also note that tdd isn't just about testing. It is a methodology of development that encourages you to create clean and solid designs.
As you are starting out tdd everything. Once you have more experience then perhaps you can back off and determine when to not tdd.
IMHO if you are not comfortable with TDD, trying to apply it in projects where you will need to interact/use legacy code it's much more complex than applying it in a project from scratch. In fact, there is a whole book about this.
HTH
My advice would be to use unit testing as often as possible.
Caveat: In my experience TDD works best when working with technologies you already have some experience with. It's often hard to write test assertions if you do not know exactly what the desired result looks like (For example, try writing the test for an ASP.NET MVC action method if you never wrote an action method in your entire life). In those cases you're probably better off writing unit tests after implementing the code.
If I am developing something without a user interface, I always use TDD these days. After all, you have to test the software. You can either do the extra work and do TDD, or you can do the extra work and cludge together a user client just for testing. The former tests more completely and in a more repeatable fashion.
Doing TDD against user interface code, on the other hand, hasn't really delivered much value for me. For various business reasons I'm restricted to Visual Studio out of the box for my work, and "recording" tests with VS is a huge time sink, especially when you have to re-record them if you change the UI. I do TDD for the business logic behind the UI, but not the UI itself.
I know that unit testing is desirable, and I am interested in doing unit testing. The only problem is I have no idea how, or even where to start really. So my question is: How do I learn about and start unit testing? Specifically I frequently write Java code in NetBeans and C# code in Visual Studio and am interested in what tools to use and how to get my feet wet. Can anyone offer any advice for an absolute unit testing n00b?
I know that there are a lot of somewhat similar questions out there but I am less interested in why and more interested in how.
Try to read on StackOverflow, tag unit-testing :)
Is Unit Testing worth the effort?
How to make junior programmers write tests?
What is unit testing?
How do you know what to test when writing unit tests?
Another entry point would be the tags junit and nunit
There are lots of question dealing this.
If you're searching books about Unit Testing, try this thread:
Good C# Unit testing book. There the famous Kent Beck book is mentioned, "Test Driven Development By Example".
It's worth reading!
Good luck!
This Tutorial for writing JUnit tests in NetBeans should give you an idea how unit testing is done technically. NUnit for C# works pretty much the same.
For an advanced view of how to integrate unit testing into you daily development, the standard reference is Kent Beck's "Test Driven Development By Example". Here's a broad overview.
If you really want to understand unit testing (and get hooked), try it out, it should only take a few hours!
First, I recommend downloading a unit testing framework, such as NUnit (if you want to start with .NET / C#).
Most of these frameworks have online documentation that provides a brief introduction, like the NUnit Quick Start. Read that documentation, then choose a fairly simple, self-contained class for which you are responsible. If you can, try to choose a class that:
Has few or no dependencies on other classes - at least not on complex classes.
Has some behavior: a simple container with a bunch of properties won't really show you much about unit testing.
Try writing some tests to get good coverage on that class, then compile and run the tests.
Unit testing is simple to learn and hard to master (apologies for the cliché, but it is appropriate here), so once you've done this, start reading around: for example, guerda has provided several excellent links in another answer to this question.
Start small.
Unit testing (and automated testing in general) isn't a silver bullet, doesn't always apply to every situation and can be a bit of a culture shock. That said, if you're writing software that you're selling or that your company relies on, I highly recommend adopting it. You'd be surprised how many professional development shops don't.
First, get comfortable the mechanics of creating and running unit tests with your development tools.
Then, start with a new (preferably small, but not necessarily trivial) class or method that you want to test. Writing tests for existing code has its own challenges, which is why you should start with either something brand new or something that you are going to rewrite.
You should notice that making this class or method testable (and therefore reusable) has an impact on how you write the code. You should also find that thinking about how to test the code up front forces you to think about and refine the design now instead of some time down the road "when there's more time". Things as simple as "What should be returned if a bad parameter is passed in?". You should also feel a certain amount of confidence that the code behaves exactly the way you expect it to.
If you see a benefit from this exercise, then build on it and start applying it to other parts of your code. Over time, you'll have confidence in more and more of your software as it becomes more provably correct.
The hands on approach helped get my head around the subject better than a lot of the reading material and helped fill in the gaps of things I just didn't understand. Especially where TDD was concerned. It was counter-intuitive until I actually tried it.
Find-a-bug-write-a-test
The next time you find a bug in your code base, before fixing it, write a test. The test should fail. Then, fix the bug. The test should pass.
If the test doesn't pass, there's either a bug in your test, or a bug in your fix.
A person will never find that bug in your code again. The unit tests will find it (and faster than a person can).
This is definitely a small start, but it gets you into testing. Once you've got the hang of it, you'll probably start writing more tests, and eventually get a knack for how code will fail and which tests you need (for example: a test for every business rule).
Later in your progression you setup a continuous integration server, which makes sure your codebase is always solid.
A good start is to buy a good book where you can read about unit-testing.
I have a tips on a book called "Software testing with visual studio team system 2008" and it takes you trough the basics stuff and background to more higher levels of unit-testing and practises.
Check out The Art of Unit Testing by Roy Osherove, it's a good book for beginners since it starts at the very beginning.
I would recommend reading Michael Feathers' "Working Effectively with Legacy Code". Old code often ends up being code that's hard to Unit Test. Feathers' book is a great guide in how to refactor your code to the point that unit tests are a snap to write.
Not exactly an answer to the question you asked, but might be a missing step between where you are, and where you need to be to implement some of the answers others have given.
Is the real benefit in TDD the actual testing of the application, or the benefits that writing a testable application brings to the table? I ask because I feel too often the conversation revolves so much around testing, and not the total benefits package.
TDD helps you design your software. The tests becomes the design. By writing the test first you think about your code from a consumer perspective, making a more user friendly and more compact software design.
Also, by applying TDD you typically end up writing your code in a way where you can supply test mocks and stubs. This leads to less coupled software, making it easier to change and maintain over time.
So I guess allot of the talk around TDD is about testing, but by doing that other big benefits follow, such as quality (coverage), flexibility (decoupling), better design (think as the consumer of the API).
The real improvement is that it is a good way to force you to really think through the design and implementation. Then, once you've prepared the tests and written the code, solutions to unforeseen problems appear more easily.
Something that usually happens to me that is a good analogy: When I'm going to post a question to a forum or IRC channel, I like to have the problems well written and fully described, many times the process of preparing a well written and complete description of the problem magically makes the solution appear.
The real benefit of TDD is supposed to be that it allows you to modify/refactor/enhance your application without worrying about whether you've broken existing functionality. The fact that writing unit tests tends to result in loosely coupled code and better architecture isn't necessarily the point of TDD, but I think it's hard to have one without the other.
You can't really experience the benefit of TDD unless you have unit tests with good coverage. In order to do that, you're going to have to write testable code. That's why the two are often used in conjunction or in place of one another.
Automated testing is such a time saver and confidence booster when you are developing a product that you'll ship multiple versions of. With automated tests, you know that you haven't broken anything between versions. This especially helpful when your product is something that people can write add-ons for - you don't want to break their add-ons between versions.
With TDD, you get a good suite of tests as you develop. Without TDD writing those tests is much more difficult.
Michael Feathers has an insightful blog post about this titled The Flawed Theory Behind Unit Testing. Seriously, go read it. The punch line is
All of these techniques have been shown to increase quality. And, if we look closely we can see why: all of them force us to reflect on our code.
but you should read the full post for the context.
Automated testing keeps humans from doing a machine's job.
Test-driven development maximizes the amount of automated testing.
Beyond a certain point, of course, a human is still required. You reach diminishing returns when you try to apply TDD beyond that point.