Recently I have came across an excellent book on how to develop code with testing in mind, and I wanted to share it with you. The book is called Growing Object-Oriented Software, Guided by Tests and is written by Steve Freeman and Nat Pryce.
The book starts right at the beggining as to why we want to develop test first and covers advanced topics such as testing persistance, threads, and asynchronous code. I particulary like the style with which the book delivers the message. They start by building a simple application and add new requirements to it, morphing the codebase in the process. As they do so they introduce new classes and walk the reader through the thought process considering alternatives finally choosing a solution. This gives the reader a good understanding as to what to think about when looking at code. Of course all of these changes are driven by tests, and a lot of discussion is spent on explaining why a test was written in a particular way and how to refactor it as it grows with the applications, so that tests do not become a liability.
Reading the book I sometimes felt that I was listening to myself, especially when the authors warned about global state, singletons, overusing mocks, and doing work in constructors among other things. But unlike myself, who draws sharp lines between right and wrong, the authors did a good job of presenting things on the gray scale of benefits and drawbacks. The book shows what a typical code most people will write, and then show how tests point a way towards refactoring.
If you are newbie, or an intermediate to developing with tests than this book is a must for your library!
Difference between JsTestDriver and other testing solution is the difference between flying economy and flying First Class. If you are serious about testing and TDD, than JsTestDriver is for you.
It is not another Assertion Framework
JsTestDriver as the name suggest, is not another assertion framework, but rather test runner. It can easily integrate with other assertion frameworks out there. There are already adapters for QUnit, and Yahoo Testing Frameworks, as well as Ruby autotest runner. We will help you integrate your favorite test runner.
Speed
JsTestDriver is blink of an eye fast. <angular/> is no small JavaScript project and it has about 300 unit tests and 10K lines of JavaScript. With JsTestDriver I can execute all of the tests on all major browser in under 400ms. That means that I run all of my tests on every save, giving me instantaneous feedback.
IDE Integration
It is nice to be able to run your unit tests in a browser but it is better to be able to run them from the the IDE. We have integration with Eclipse and InteliJ with instant run on every change. We even marshal the browser console into the IDE console for easier debugging.
Continuos Build Integration
If you are serious about testing, than you are serious about continuous integration. Because JsTestDriver can be controlled from the command line, it can easily integrate into your continuous build. Single command starts the browsers, runs the tests, and reports the test results in a XML file which is compatible with most continuos integration servers such as Hudson.
Code Coverage Built In
JsTestDriver allows JavaScript instrumentation on the fly, which means that it can instrument your code for coverage and generate LCOV format, which can be easily converted into source annotated report of your code. This is done transparently and works on all browsers.
Remote Test Execution
I develop on Mac, but need to test on IE. I run JsTestDriver on my build machine which can be accessed by HTTP and have IE always captured. No matter where I am in the world, I can run my tests against IE. This allows me to have a small browser farm ready to do my bidding.
Support form Mobile Browsers
Just as I can capture desktop browsers, I can also capture mobile browsers. This allows me to develop in my favorite IDE and have my tests run on every save on the mobile platform.
Best way to learn TDD is to have someone show you while pairing with you. Short of that, I have set up an eclipse project for you where you can give it a try:
It should be set up to run all tests every time you modify a file.
You may have to change the path to java if you are not an Mac OS.
Project -> Properties -> Builders -> Test -> Edit
Change location to your java
Right-click on Calculator.java -> Run As -> Java Application to run the calculator
Your mission is to make the calculator work using TDD. This is the simplest form of TDD where you don’t have to mock classes or create complex interactions, so it should be a good start for beginners.
TDD means:
write a simple test, and assert something interesting in it
implement just enough to make that tests green (nothing more, or you will get ahead of your tests)
then write another test, rinse, and repeat.
I have already done all of the work of separating the behavior from the UI, so that the code is testable and properly Dependency Injected, so you don’t have to worry about running into testability issues.
Calculator.java: This is the main method and it is where all of the wiring is happening.
CalculatorView.java: This is a view and we don’t usually bother unit testing it has cyclomatic complexity of one, hence there is no logic. It either works or does not. Views are usually good candidates for end-to-end testing, which is not part of this exercise.
CalculatorModel.java: is just a PoJo which marshals data from the Controller to the View, not much to test here.
CalculatorController.java: is where all of your if statements will reside, and we need good tests for it.
I have started you off with first ‘testItShouldInitializeToZero’ test. Here are some ideas for next tests you may want to write.
testItShouldConcatinateNumberPresses
testItShouldSupportDecimalPoint
testItShouldIgnoreSecondDecimalPoint
testItShouldAddTwoIntegers
I would love to see what you will come up with and what your thoughts are, after you get the whole calculator working. I would also encourage you to post interesting corner case tests here for others to incorporate. If you want to share your code with others, I would be happy to post your solutions.
Good luck!
PS: I know it is trivial example, but you need to start someplace.
Presented by Jeremie Lenfant -Engelmann, Google, at the 4th Annual Google Test Automation Conference, October 21st, 22nd, 2009, Zurich, CH
The proliferation of JavaScript unit-testing frameworks in the JavaScript community shows that no one has yet found the magical combination of features to make JavaScript testing a no-brainer. We like to believe that JsTestDriver will change that by redefining JavaScript testing frameworks and as a result will deliver something which at first glance seems impossible. As a developer of JavaScript I want to write my production and test code in my favorite IDE. When I make a code change, I want a save action to trigger a rerun off all of my tests on all browsers and platforms and report the results under 1 second. All of this without ever leaving my favorite IDE. JsTestDriver achieves all of the above by capturing any number of browser slaves from multiple platforms. In order to run at high speed we do not render our results in the browser but report the errors on the command line. JsTestDriver also loads and parses JavaScript files eagerly, only reloading files that have changed. JsTestDriver can execute hundreds of tests per browser and execute them on all of the captured browsers in parallel. Thanks to these practices we achieve extremely high throughput. We want to be a test-runner platform and allow others to build assertion frameworks on top of JsTestDriver. This way the open-source community can focus on building a better way of testing and not worry about how to run the tests across all of the browsers, platforms and in a continuous build environment. http://code.google.com/p/js-test-driver
Bio: Jeremie Lenfant-Engelmann works for Google and is the lead developer of JsTestDriver.
Here are my slides which Cory Smith and I have presented this morning at OOPSLA 2009.
The ability to write hard to test code is innate in every developer form the moment we have built our first “Hello World” application. It is so automatic that we do not even know when we are doing it. On the other hand writing testable code requires that you un-learn this behavior. In this tutorial you will learn how to recognize the red flags in the code and what are the common solutions for them. We will look at sample code representing common development practices and look into subtleties why this code is hard to test and how to fix it. The goal of the tutorial is to arm you with knowledge of how to write code which can be tested using small focused tests.
Automatic Dependency Injection Frameworks (such as GUICE, PicoContainer, and Spring) are very popular in Java, where they depend heavily on static typing, interfaces, reflection and annotations. But what about languages such as ActionScript, JavaScript, Python and Ruby, where duck-typing and lack of run-time-type-information at first glance make these frameworks impossible? Can a simple Dependency Injection Framework framework be built? We’ll look at how the power of functional programing and functions as first class citizens in these languages can be leveraged to build a simple and effective dependency injection framework. We’ll also explore the power of using such a framework in dynamic languages. To illustrate these ideas we will convert a JavaScript application which uses manual Dependency Injection into one using Automatic Dependency Injection Framework.
The old saying goes: Ideas are a dime a dozen, it’s the execution that counts.
So you are working on a project and all of a sudden you realize that it would be great to have a web-application which keeps track of something. It is exactly what would hit the spot, but than you think about it some more and you realize that your choices are
Custom app in php/java/ruby/rails/etc… would take you days to get up and running and than there is the cost of deployment. You have full control of everything but you have to be an expert in everything.
You could use Google docs (spreadsheet) but that does not have the right look and feel, as you can either have form for collecting data or you can have tabular data. You have zero control of the presentation.
So you think about it some more and you realize that the benefits are not worth the effort and the application does not get build. How often has this happen to you?
<angular/> is not about making the building of web-applications easier, it is about allowing you to build an application where no application would have been build before.
Let me give you an example. I do a lot of coding and often I get distracted. So I said, I would love to know the reasons why I get distracted. Would it not be great if I could keep a log, which would than draw a chart for me with how often and why I get distracted? I could have opened a spreadsheet, but somehow the act of opening a spreadsheet is a distraction in itself, so I doubt I would have done it every time I got distracted. So instead I took 5 minutes to hack together a quick HTML which allowed me to enter the reason why I was distracted in <angular/>. Now I am a mac user, so I click the “Open in Dashboard” on my safari and I had a dashboard widget which allows me to keep track of the reasons whenever I get distracted, with very little effort. I stop coding because I need to go to meeting, I activate Dashboard and enter the reason, someone comes over and asks me a question, ditto.
<angular/> allowed me to go from an idea to working app in 5 minutes. If it was not for <angular/> this simple app would simply not get built. It is great when technology makes existing things easier, it is even better when it enables things which simply would not have happened.
Wait! I have an idea, it would be great to get your opinion on what kind of quick and dirty applications you always wanted to build but the effort was not worth the benefit. What if, we could also vote on other peoples ideas too.
Building web-applications is hard! Even the simplest hello world application will take you hours to set up and you have to know a lot about how many different pieces of technologies work together. Here is a quick inventory from the browser to the back end of what a typical web-application developer needs to know about: HTML, CSS, JavaScript, cookies, HTTP, URL encodings, Servlets, web-framework (i.e. web-work), authentication, threading, SQL, ObjectRelational mappers, DB Schema, RDMS, DB indexing. If you know all of that, than you have a good chance that after week of work, you can have a hello world application written which will allow the user to authenticate, and persist some data.
But, if you think about it most web-applications are just pretty UI on top of database CRUD (create, read, update, delete). Everything else you do is a constant marshaling of data back and forth. From the HTML input, to URL parameters, to HttpRequest, to BussinessObject, to Value Object, to SQL. Hope you did not make any mistakes, as now you have to do all of this in reverse.
The goal of <angular/> is to make CRUD applications easy to build. <angular/> is not a generic framework where you can build any kind of application, its sweet spot are CRUD web-applications.
We believe that there are many web-application which do not get build because the cost of building them is prohibitive. With <angular/> the cost of building these simple applications is greatly reduced.
While building <angular/> we had few goals in mind:
Managed Database
Building a web-applications is just half the battle, deploying them is another. Now you need to rent a host in the data-center where you can deploy the application, where the database can run. I hope you know how to administer and back up your database. <angular/> provides the database hosting as a service so that your <angular/> application does not have to worry about it.
HTML & CSS
There are a lot more web-designers out there than web-developers. We wanted to make <angular/> simple enough where many of the web-designers, which do not know how to program can now move to the business of building simple web-applications and hence provide a greater value to their customers. In order to build a simple web-application a knowledge of HTML & CSS is all which you need to know. The best way to think about <angular/> is that it is HTML with few extra attributes.
Security/Authentication
The cost of building security and authentication into your web-application is often overlooked when building web-applications. <angular/> offers both out of the box.
Embeddable
There are many ways to get your HTML published. (Blogs, Wikis, Content Management systems, to name a few) <angular/> allows you to enhance all of these pages behavior by adding the power of CRUD to these pages. Embeddability opens up a whole new set of possibilities of enhancing existing web-pages or creating mash ups.
Declarative
I can teach HTML to almost anyone (willing to learn) in just a few minutes. Teaching programming languages such as JavaScript requires weeks of work, and that is if you already know how to program. The difference is that HTML is declarative whereas JavaScript is procedural. You describe how the page looks like, vs instructing the browser how to draw one. This is a huge for the learning curve. Declarative vs procedural is the difference between web-designer and the web-developer.
Rich Widgets
Finally, HTML forms have very limited widgets, you want date-picker? charts? maps? form validation? barcodes? formatters? well you have to go and integrate some JavaScript library and you have to know how to program (vs declaring what you want). We want to extend the HTML so that you can ask for these widgets in declarative fashion in <angular/>.