So I have been trolling through code on my current project lately checking tests and test quality. One of the things that I have been seeing a lot of lately involves tests that have what I consider to be too intimate knowledge of the classes they are testing.
When you write *good* tests using TDD you test the expected behavior of the method/class. Done correctly you will create the failing test, make it work, and then refactor intelligently for clarity and better design. This is not a revelation to anyone doing TDD or experienced in agile practices.
What I find is that much of the code I am reviewing seems to be characterization tests that were retrofitted onto the code for coverage purposes more than real *testing*. By this I mean the class was written first or in conjunction with the tests and that the tests verify the execution of the code rather than a behavior or expectation.
The result ends up being a test that has way more knowledge of the implementation of a behavior than it should. It also results in bad design.
A good example is a Portlet servlet. A servlet is built to support the rendering of a portlet and without doing TDD up front what resulted is a servlet class that implements most, if not all, of the business logic. This results in two big issues. First, the business logic gets tied tightly to the portlet and servlet specs and requires a lot of mocking of requests, responses and session objects and the method invocations. Big pain in the a**.
Second, because the logic is in the servlet, you miss the opportunity to place the logic in a service/bean class where it belongs. That class would be much simpler to test.
More importantly, if the logic is separated out properly you have the ability test the behavior instead of the implementation as you no longer need to worry about the container details that waste your time. No effort spent setting up the container state, you only focus on the business logic.
This also means you can better test *what* you want to do rather than worrying about *how* it is done. You can focus on the results and refactor without fear when green.
I am sure you can think of dozens of examples of this yourself. I find this tends to happen because a) the developer is new to TDD (or isn't experienced) and/or b) there is a strong push for getting coverage on the code rather than pushing for quality tests (which will result in good coverage.)
Thursday, December 10, 2009
Wednesday, November 18, 2009
Who Does Testing?
I just recently followed a tweet and read a blog post by Steven Baker (here) that discusses his frustration with the Dev vs QA scenarios that constantly come up in the development process.
Being an Agile/Lean proponent the whole concept of differentiating developers from QA makes no sense to me. My job as I see it to to build the product the user wants. Period. Obviously, if the product doesn't work as the Product Owner expects it to work I have not done my job.
This seems reasonable, doesn't it?
I can't imagine developing a product without putting unit, integration and acceptance tests in place. How do I know what I have created works and works as the customer wants without these tests? I get the stories from the business folks and create the tests to ensure that I have written the code to do what they want, no more no less.
Why should this be a QA job? I know what is to be built and since I am the one doing the coding it makes sense to me to make sure it does that when I am creating the code. For me to write some code and then throw it over a wall to someone else to test delays the feedback one whether it is really working. It is waste that should be eliminated as it becomes more expensive to fix once it gets that far.
While I realize that there is a special skill set required to do superb testing, having a delay in the flow of the testing just delays everything and adds to the time, cost and frustration when defects or misunderstood requirements occur.
I prefer to have an integrated team of developers and testers. There are folks who specialize in testing and folks who specialize in developing. Having them integrated on a team and working together cross-functionally during construction allows us to catch things sooner and also allows us to learn from each other and enhance both of our skill sets. We get better insight into each other's worlds and merge them.
The result is that I am better at my job and they are better at theirs. We also eliminate the artificial wall between us. There is a Yin/Yang relationship to coding and testing - one does not exist without the other and so we are two sides of the same coin.
Being an Agile/Lean proponent the whole concept of differentiating developers from QA makes no sense to me. My job as I see it to to build the product the user wants. Period. Obviously, if the product doesn't work as the Product Owner expects it to work I have not done my job.
This seems reasonable, doesn't it?
I can't imagine developing a product without putting unit, integration and acceptance tests in place. How do I know what I have created works and works as the customer wants without these tests? I get the stories from the business folks and create the tests to ensure that I have written the code to do what they want, no more no less.
Why should this be a QA job? I know what is to be built and since I am the one doing the coding it makes sense to me to make sure it does that when I am creating the code. For me to write some code and then throw it over a wall to someone else to test delays the feedback one whether it is really working. It is waste that should be eliminated as it becomes more expensive to fix once it gets that far.
While I realize that there is a special skill set required to do superb testing, having a delay in the flow of the testing just delays everything and adds to the time, cost and frustration when defects or misunderstood requirements occur.
I prefer to have an integrated team of developers and testers. There are folks who specialize in testing and folks who specialize in developing. Having them integrated on a team and working together cross-functionally during construction allows us to catch things sooner and also allows us to learn from each other and enhance both of our skill sets. We get better insight into each other's worlds and merge them.
The result is that I am better at my job and they are better at theirs. We also eliminate the artificial wall between us. There is a Yin/Yang relationship to coding and testing - one does not exist without the other and so we are two sides of the same coin.
Friday, November 6, 2009
Release Retrospectives
The Agile dev team/project I am currently engaged at recently released version one of the application. The application is a K-12+ knowledge portal for animal information. The portal itself is really interesting and I have had a lot of fun working on the project and I have also learned and honed a lot of my agile skills while here.
So anyway, we released the product into the wild and it is getting great reviews. It is pretty solid while employing lots of moving parts.
During the development we went through a typical Scrum style process - daily standups, poker planning,iteration planning, business verification (show n' tell). We also did weekly retrospectives for the previous iteration. It was a fairly boilerplate operation.
Once we released the product we had a release retrospective with the entire team - Product Owner, Dev Team, Content Team, and QA team. Just to be clear the whole team works together in an open agile space with pairing stations and the board, etc so we were in constant contact with each other for the whole lifecycle.
The release retrospective went better than I anticipated it would since I had met some resistance to points I had brought up in the past at iteration retros and I tend to be a rather blunt, no BS person. I don't like mincing words and that can get me in trouble at times but, well, that's just me.
So we executed the retro using the same basic formula that we used and I am sure everyone has some experience with. WE did the standard "What went well, What didn't go well, What can we do better" and then we determined which points to improve were the priority and who would lead those up for the next go round.
There were many good points brought up during the retrospective. The initial "What went well" section had valid successes such as good cross team communication, Product Owner availability, quick resolution to technical problems, etc. We ran into some nasty issues in piecing the app together and our team and especially the Tech Leads were very good about figuring out what was wrong and how to fix it.
The "What didn't go well" and "What can we do better" portions are more interesting to me as these are the ones that drive process improvement and lead to smoother development later. We covered a lot of ground with these and identified many things that were important to getting things to flow better. Things like paying better attention to skill buckets and avoiding knowledge silos were brought out. Trying to achieve something closer to push-button configuration for the pairing stations was another item given the problems we had with keeping workstations relatively synchronized was another point we wanted to address.
After we went through the process of discussing our good, bad and uglies we all then voted by placing checkmarks next to three items in each column that we as individuals thought were the biggest priorities going forward. We tallied the votes and chose the items with the most votes as the topics we planned to pay particular attention to in the next release.
The whole experience was a good, cathartic exercise for the group. We had the opportunity to address points that we all felt were important to discuss, we had the opportunity to voice our opinions about everything related to the release, the team and the process, and we were able to get it out of our systems in a healthy way that will hopefully assist us in continuous improvement for the next release.
If you aren't currently doing release retrospectives then I encourage your team to think about it. It doesn't take a long time to do it and it has the potential to remove roadblocks to future success. And it is empowering to the team to know that their input matters.
Friday, October 9, 2009
It's Just Syntax
I have been a developer for more than 15 years. I have written a lot of code in that time and have seen the profession of software development grow and mature in that time. Many things have evolved and the old way of doing things drops away as the newer practices come in to replace them.
I am not new to agile but I am also not a guru. I learn something new everyday and one of the more interesting things I have recently experienced is TDD and mocking in a new language. Not a new one on the scene but a new one to me - C#.
Now for many this seems kinda strange since Visual Studio, .Net and C# have been in the mainstream for a long time. I haven't used Microsoft development tools since Visual Studio 6 and even then it was for VB. I have been in the Java world since 1998 or so and it came to be my dominant language over time. I have played with Ruby, Groovy and a bit of Erlang but primarily I have a Java geek for a while.
That being the case, all of my real world agile experience has been learned and internalized using Java and JEE.
So...
I get a client who needs something done fast. The caveat is that I know this client from way back and I know that it has to be Windows-based, it needs to be one click install and feel native. Naturally there are ways to do this with Java, and Ruby an the rest but, really, on a Windows box for a console type app VS with a standard msi install is just a natural fit. This is what leads me to think "Well, I guess I will take this opportunity to see what it looks like in MS these days and since I have done VB but not C#, why not?"
A natural thought and so I take the plunge. This is where it gets interesting because since the last time I worked with MS and VB I have become an agile developer who needs my TDD and Mocks to know I am doing code right an doing just what is required an no more than is required to built the product correctly with high quality. This is the natural way for me to work and so I look into tools for this.
I came across NUnit and I was pretty happy since it crrelates really well with my Junit experience. Then I find RhinoMocks and Moq and I was pretty happy with those too. I turn my sights on a coverage tool and I hit a wall.
Visual Studio Team has the coverage but I am not going to shell out that kinda money for a "team" product when all I need is the coverage piece, Professional Edition is fine. There must be something else. The product that gets all the mentions is Ncover with looks really nice. The problem is that it went commercial and is a bit pricy for a single tool, especially after I spent the money on VS Professional.
Finally I come across the cost effective answer - TestDriven.Net. It bundles Nunit (several versions) and Ncover in a single tool that integrates right into VS. Sweet. The whole setup meets my desires and I start working.
I am sure I am not the first one to experience culture shock taking my customary agile practices from one language to another but I will say that I was mighty surprised at the roadblocks I came up against. I am not going to run down a big list of the problems because it could be construed as a critique or rant on MS and Visual Studio and that is not my intent. In reality I am impressed with some language features.
My difficulties revolved around the fact that much of what I considered to typical TDD methods are really very Java-centric TDD. An example is the abilty to inline override a protected method of a class online in a test to provide stub or fake behaviour of the class you are testing. This is a simple an favorite technique to override simple things light property configuration.
Another thing is that accessor methods in .Net don't work the same way as Java's do. And why should they? Stupid assumption on my part. Adding to this that packages don't equal namespaces and where your tests are in the same namespaces as the class you are testing you still don't have access to protected methods because friendly doesn't work the same either. Again, why should it and dumb assumption. What this leads me to is a lot of public methods where I don't want them public.
Now before I get a deluge of "You missed the obvious!" I will state for the record that I probably have missed the obvious. I realize that. But that isn't the point of this post.
The point is that I am learning that much of you TDD skills are very dependent on your language and development environment an it helps to be aware of this. I am coming up with new techniques, possibly better techniques, for doing testing in a different world. And I believe this makes me a better developer for it. You have to adapt to change and changing the dev environment and language is a fundamental way to teach you to do that.
I am still good at TDD and I am still good at agile. I have to learn to adapt and develop in ways that I wouldn't have had I stuck with my comfort zone. And the next time I switch languages I will be ready and I think I will cope better. Best of all I will know that TDD and agile is possible regardless and, as every developer who has been around a while will tell you, it's just syntax.
In the long run most concepts in programming aren't that different. It is really about knowing the concepts and learning where to put your fingers on the keyboard.
-- JMH
I am not new to agile but I am also not a guru. I learn something new everyday and one of the more interesting things I have recently experienced is TDD and mocking in a new language. Not a new one on the scene but a new one to me - C#.
Now for many this seems kinda strange since Visual Studio, .Net and C# have been in the mainstream for a long time. I haven't used Microsoft development tools since Visual Studio 6 and even then it was for VB. I have been in the Java world since 1998 or so and it came to be my dominant language over time. I have played with Ruby, Groovy and a bit of Erlang but primarily I have a Java geek for a while.
That being the case, all of my real world agile experience has been learned and internalized using Java and JEE.
So...
I get a client who needs something done fast. The caveat is that I know this client from way back and I know that it has to be Windows-based, it needs to be one click install and feel native. Naturally there are ways to do this with Java, and Ruby an the rest but, really, on a Windows box for a console type app VS with a standard msi install is just a natural fit. This is what leads me to think "Well, I guess I will take this opportunity to see what it looks like in MS these days and since I have done VB but not C#, why not?"
A natural thought and so I take the plunge. This is where it gets interesting because since the last time I worked with MS and VB I have become an agile developer who needs my TDD and Mocks to know I am doing code right an doing just what is required an no more than is required to built the product correctly with high quality. This is the natural way for me to work and so I look into tools for this.
I came across NUnit and I was pretty happy since it crrelates really well with my Junit experience. Then I find RhinoMocks and Moq and I was pretty happy with those too. I turn my sights on a coverage tool and I hit a wall.
Visual Studio Team has the coverage but I am not going to shell out that kinda money for a "team" product when all I need is the coverage piece, Professional Edition is fine. There must be something else. The product that gets all the mentions is Ncover with looks really nice. The problem is that it went commercial and is a bit pricy for a single tool, especially after I spent the money on VS Professional.
Finally I come across the cost effective answer - TestDriven.Net. It bundles Nunit (several versions) and Ncover in a single tool that integrates right into VS. Sweet. The whole setup meets my desires and I start working.
I am sure I am not the first one to experience culture shock taking my customary agile practices from one language to another but I will say that I was mighty surprised at the roadblocks I came up against. I am not going to run down a big list of the problems because it could be construed as a critique or rant on MS and Visual Studio and that is not my intent. In reality I am impressed with some language features.
My difficulties revolved around the fact that much of what I considered to typical TDD methods are really very Java-centric TDD. An example is the abilty to inline override a protected method of a class online in a test to provide stub or fake behaviour of the class you are testing. This is a simple an favorite technique to override simple things light property configuration.
Another thing is that accessor methods in .Net don't work the same way as Java's do. And why should they? Stupid assumption on my part. Adding to this that packages don't equal namespaces and where your tests are in the same namespaces as the class you are testing you still don't have access to protected methods because friendly doesn't work the same either. Again, why should it and dumb assumption. What this leads me to is a lot of public methods where I don't want them public.
Now before I get a deluge of "You missed the obvious!" I will state for the record that I probably have missed the obvious. I realize that. But that isn't the point of this post.
The point is that I am learning that much of you TDD skills are very dependent on your language and development environment an it helps to be aware of this. I am coming up with new techniques, possibly better techniques, for doing testing in a different world. And I believe this makes me a better developer for it. You have to adapt to change and changing the dev environment and language is a fundamental way to teach you to do that.
I am still good at TDD and I am still good at agile. I have to learn to adapt and develop in ways that I wouldn't have had I stuck with my comfort zone. And the next time I switch languages I will be ready and I think I will cope better. Best of all I will know that TDD and agile is possible regardless and, as every developer who has been around a while will tell you, it's just syntax.
In the long run most concepts in programming aren't that different. It is really about knowing the concepts and learning where to put your fingers on the keyboard.
-- JMH
Subscribe to:
Posts (Atom)

