You probably know the rest of this quote, but likely have no idea where I’m heading with it. Well, it’s a brief conversation about making snap judgments.
At a client recently, we were discussing the effects of code coverage, code complexity, code dependency and other automated analytics and whether developer testing actually improves the ability of a company to effectively deliver software applications.
I was internally amused when a developer said, “This one time, we hired a guy who was a big-believer in JUnit, but his code wasn’t any better than mine.”
That was his objection. In total. One time he was underwhelmed with a colleague, so he really shouldn’t give any credence to reconsidering the topic.
It might be laughable if it wasn’t common. In fact, as a society we promote the idea of quick, intuitive decision-making. Malcolm Gladwell’s book, Blink: The Power of Thinking Without Thinking is a great example of modern trends about instinctive reasoning.
The concept of “diagnosis momentum” in medicine is not dissimilar to development teams who are myopic in evaluating how they produce software. The best answers are found when you move forward with “deliberation, caution and systematic thinking.”
The next time you suggest a new change to your team and a fellow member starts an objection with, “This one time,” I hope you remember the “band camp” scene from American Pie. Try not to laugh out loud, but do try to challenge the notion that such a limited experience set is not of great value when contemplating change.
So, what’s your experience? Do you work with colleagues that often have an objection based on single-case experiences? Are they influencers or ignored? How do you lead them towards more deliberate examination?
A client I worked with recently had a very astute characterization of Continuous Integration. I will paraphrase it as “CI is a reflection of reality”. He was referring to the immediate feedback you receive from a successful or failed integration build. Using a single source (your version control repository), you’re able to quickly determine if any of your recent changes “played well with others”. Not tomorrow, not two weeks from now, but immediately after a change is made. It reminds me of something Bill Cosby used to say in one of his stand-up routines when someone mentioned they liked using cocaine because it “…intensifies your personality”. Cosby’s response was “Yes, but what if you’re an a**hole?”. CI provides you with a mirror of your software under development. It’s not the fault of CI if it comes back and tells you your code is not working as intended. If fact, you should embrace it before it tells you it’s ugly.
Since I’ve heard many conflicting definitions on what a software “build” actually is/is not, I figured I’d come up with my own definition to muddy things even more! Someone on Wikipedia has described a software build as “the process of converting source code files into executable code or the result of doing so.” Without parsing words, I think that this is, currently, the generally accepted definition of a build. However, I’d like to expand this definition to include much more than the mere compilation of source code files into something that can be executed. Unfortunately (for many it seems), compilation is often the end of the development line as a developer moves onto his next task. Some people will also “unit test” their code, which means they test a small part of the application functionally (btw, this is NOT a unit test). I think a build is converting source code files into executable code and validating and verifying that it works as expected. What does this mean? To me, it means that a build should consist of compilation coupled with execution of automated developer tests (unit, component, system, and so on), execution of automated inspections (code coverage, cyclomatic complexity, duplication checks, and so on), and packaging/deployment (to a server or other environment). The “compilation” piece may include rebuilding the database and test data to provide a consistent environment from which to execute tests. You’ll often hear people refer to “build and test”. It seems to me this terminology is used because most people still think of a build as nothing more than the compilation (and linking, etc.) piece. I think “builds” should refer to much more than the compile and, in fact, the flimsy use of the word leads many to think they’re done with their development once they click the “Run Build” button in their IDE. What do you think?
The co-founder of CruiseControl, Paul Julius, shares an experience that demonstrates how practicing CI saved $12,535 for one defect on one project by discovering and fixing the defect shortly after it was introduced. Some people ask “what’s the return on investment of CI?”. Although, software quality is a great benefit of CI, this experience demonstrates the amount of money that can be saved by effectively using the practice.
I was honored that Paul wrote one of the forewords for the upcoming book on Continuous Integration due out next month. In the foreword, he shares an excellent perspective of his experiences and contribution to the CI practice.
While programmatic testing isn’t for everyone (non-developers will likely prefer Selenium’s Fit-style tables), it does give you access to TestNG’s exceptional flexibility….
TestNG is an especially good match for Selenium because it enables you to do some things that aren’t possible using other frameworks, such as test using dependencies, rerun failed tests, and set up parametric tests with the parameters defined in separate files.
…. and also allows you to build out your test framework with DbUnit and Cargo, thus ensuring the logical repeatability of your tests.
Don’t miss out on the code quality discussion forum where you can learn first-hand about code metrics, test frameworks, and writing quality-focused code.
I was at CITCON last weekend and someone asked me about managing the CI server configuration files (such as with CruiseControl). I told them that I like to manage my configuration files just like any other software project. The build and CI scripts are not “second-class citizens” when I’m developing software.
First, I create a project in my version control system to manage the files that manage my CI server. Then, I create a project within my CI server to poll for changes against the project in the version control repository. If any changes are found, it retrieves the files and overwrites any relevant files in the CI server directory location (e.g. /opt/cruisecontrol-bin-2.6.2/config.xml). In this case, you’re using the CI server to look for changes and then overwrite its own configuration files….it reminds me of the ‘Dancin’ with Myself’ song by Billy Idol (1982). The code listing below shows a CruiseControl project called cc-config that polls a Subversion repository which contains CruiseControl configuration files. If changes are detected it calls the delegating build, ${build.config.file}.
The next code example is the delegating build in Ant. This build cleans any local files and gets the new files from Subversion. Finally, it calls the cc-config project’s build.xml.
The final example is the Ant script that does the actual work, the build.xml. It copies the files retrieved from Subversion and updates these files to the CruiseControl configuration directory, /opt/cruisecontrol/cruisecontrol-bin-2.6.2.
There are a couple of things to keep in mind if you are using this technique. If you make any changes to configuration files (e.g. /opt/cruisecontrol/cruisecontrol-bin-2.6.2/build-project.xml, etc.), directly on the server, they’ll be overwritten by these changes. The other thing is that if you make changes to the config.xml, they won’t be effective until the next build because it uses the config.xml to find changes to “itself”.
Is anyone using a different technique to solve this issue? Are you managing your CI server changes in your version control system? Is this too extreme?