Thursday, August 23, 2012

Zend Server

I'm in a demo of the next version of Zend Server.  The UI is nice.  Permission are a welcome feature.

Tuesday, August 21, 2012

Jimmy’s bad experience with TDD. Was it really TDD?

Jimmy is introduced to test driven development. He has all these shiny tools that have unlimited power. Naturally, he only substitutes his current style (code-> run->point click test) with an automated test test runner. After a few days learning curve Jimmy is happy, he is cranking away on his current project and getting more done than he ever imagined. He has confidence in what he is writing because everything is green. Life is good.

Then all the sudden,some of his tests are not green but red. He reverts his code to a previous version, still red. He reboots his computer, still red. Starts debugging, only to find the data changed. The DBA’s cleaned out all the test data. Jimmy has an idea, he will use his new shiny tools to create scripts to check if the data is in the database, if not, it will populate. He spends a few days getting it just right and working with his unit test. Everything is green again, life is good. He starts coding again. Then his data population scripts start acting funny. The DBA’s changed the structure. Jimmy, while frustrated makes changes.

Then the stakeholder asks Jimmy to make some changes to the site, the changes are not small, but not too big either. But Jimmy finds that to make the changes requires more work than he is used to because he has to refactor his code, then make changes to the test, right in the middle of this process, more database changes come in. Jimmy is getting nervous because he is running out of time. Faced with the reality that is project may be late, he essentially abandons his tests, makes the changes to his code to make the stakeholder happy. He has every intention of coming back to ‘fix his tests’. He never does.

Jimmy is not the biggest fan of unit testing. He avoids it for the next few projects.

Then one day, Jimmy is assigned to a management console project. This project is painful because every little change is a pain to test. He has to run the app, log in, click through 5 different menus, fill out a form with a bunch of required fields and then submit. Development is slow and not very much fun. Jimmy know he can get around some of these problems by shifting his coding style a bit, then he can use his unit testing tools, mainly the test runner, to save some time. But when that project is over, so is the testing. He would like to do more, but bad experiences have soured his enthusiasm for what he thought was TDD. In reality Jimmy never really did TDD.
This story was written for an intro to a presentation on TDD.

Friday, August 17, 2012

Fail Safe Test Driven Development

 

Terms

Dependencies – Anything outside of your code.  Database, files, web services,

Dependency Injection framework – framework to help you manage which concrete dependency to use based on a given context.  Example, use mock of ISqlRepo when testing but use real Sql2008Repo when not testing.

Testing Framework – usually has a test runner to run the tests and display the results of each test.  Usually has code framework to create assertions.  eg. Assert.IsTrue( 4 = 2 + 2);

Inversion of control – where you allow the calling method to have a say in how something is done.  saveUser(user, dao)    vs.  saveUser(user)

Mocking – Since you cannot new up an interface, a mocking framework will allow you to create a concrete object from an interface, or override existing functionality in a concrete class.  There are many fun things you can do with mocks like make them observable.  Then you can assert that a certain method is only called a certain number of times.  This can be surprisingly helpful.

Composability – think buffet, you can pick and choose.  Developer has a high degree of control.  vs. happy meal.

Test Friction – how hard is it for you to test your app

Repository Pattern – in short – new up an data model object for you with data.  If your data models are POCO objects, your repo get data from database or other and returns them to the app.

POCO/POPO – Plain Old C Object, Plain old PHP object – object with fields or properties no methods, save maybe getters and setters.

Smurf Naming Convention – When all the classes start with the same thing but add the action eg, CustomerOrderService, CustomerOrderRepo, ICustomerOrder, CustomerOrderDataModel


Tools

  • Language that supports TDD
    • HTML and CSS are not programming languages – limited ability to test
    • SQL is not a programming language – not easily suitable for TDD
  • Testing Framework
  • Mocking Framework
  • Dependency Injection Framework
You do not need a database, file system, browser, web server, version control system.  You should have version control, but you do not need one that supports testing to do TDD.

Philosophy

  • Highly maintainable
  • Low test friction
  • Inversion of Control
  • Loose coupling (not independence) 
  • Composability
  • Helping yourself and others
  • TDD is NOT about customer satisfaction or satisfying product requirements
  • TDD is about embracing the power of the native programming language, not reducing it to one line of code or hiding it.
  • Protect your code from dependencies
  • Avoid the temptation for integration testing – you will fail
  • Be prepared to work around what you cannot test.

Layers

The layers in an app are highly dependent on the app and the goals of the app. You may need each layer to be portable for other projects. On they can just be folders in your existing project.

  • Data Models
  • Application Interface
  • Repo Interface
  • Business Logic – no dependencies 100% your language and under test
  • Application – this is where the layers come together in a loosely coupled fashion to create your app. Your app is just a composition of each of the layers.
  • Tests – not really a layer but should be part of your solution but not part of your application.

Rules

  • Static methods are bad
  • Private methods are bad
  • Starting with tests is important if you want the tests to drive the development 
  • Public methods are good
  • Interfaces are good – how you can control the supported footprint (vs. private methods)
  • Repository Pattern is your friend
  • In MVC skinny models and fat controllers
  • Use constructors to set your dependencies
  • Layers – this requires some practice and discipline
    • Tests should never reach into the application layers
    • Data Models have zero dependencies except the language (PHP, C#, Java)
    • Interfaces have one dependency: Data Models
    • Business Logic – one dependency:  data models (sometimes interfaces)
    • Repository – data models, and any database libraries, cannot reach into the application.
    • Application Logic – Data Models, Interfaces, Business Logic, Repository, Dependency Injection Framework, and many more.  This is where the composition happens.

Workflow

  1. Create a sunny day interface test
  2. Create Data Models (POCO)
  3. Create Interface for repo or service – all depends on what you are building
  4. Use interface to create a mock object that you can test.

After you have a working test, start working backwards, start working on an implementation from the interface.  Create a new test, exactly as your mock but return your implementation not your interface.

Sample

https://github.com/dominionenterprises/FailSafeTDD