Category Archives: Perl

Unit Testing Your Code (aka Test-Driven Development)

A few years ago, I scheduled a meeting with the software engineers on my team to introduce them to Test-Driven Development (TDD).

I had started reading the book “How Google Tests Software” and I felt I had to share what I was learning. I started a book study with the team.

The first thing I wanted to focus on was unit tests. This was a completely new concept to the team and to me. I looked around online and found some good tutorials and a video from a teenage developer who was showing other engineers how to write their first unit test.

I built a Google slide presentation and walked through it with the team.

One of the first slides focused on the reasons (excuses) why engineers don’t write unit tests:

  • It’s too late to start
  • It’s too much work
  • It has to be maintained
  • It slows down real development

For each of these reasons, I added a translation into what it really meant:

  • I don’t know where to start.
  • This looks scary. Am I a tester or a developer?
  • I don’t want to maintain this code, too!
  • I have deadlines for real features!

My goal was to head-off the concerns early. I put myself in their shoes, thinking about what it would mean to add unit tests to my code. One thing that really hit home with me was “I don’t know where to start.”

I encouraged the team to start writing unit tests. I showed them the video of the teenager writing them. I called him “Kid Coder” and I told the team — “If Kid Coder can do it, you can, too!”

It worked, the team started writing unit tests. Most never got to the point of actual test-driven development where the tests are written first followed by the code. But we now have thousands of unit tests to go with our many projects.

The second half of my presentation — which we covered on another day — focused on the role of software engineer in test (SET). I wanted to train them on this concept because one of our next steps was to hire an SET and to set up a build server which could also run our unit tests.

It wasn’t long before we hired our first SET and set up a Jenkins server. Not only do we now automate unit tests, we’ve also automated our builds, our code style checks and more. We spawn test nodes in the cloud when we are testing certain projects and more.

It’s come a long way since that first presentation.

Now, I don’t write code too often. My team discourages it! 🙂 And I have other things to do. But I have a few side projects — some for business and some for personal use. I have a lot of code to support web projects. I write in Perl — and I’ve gotten pretty good at it

Can you guess the one thing that I had never done? You got it — I had never written a single unit test.

What a hypocrite. What had been blocking me? I didn’t know where to start.

This weekend, though, that changed. I did some research on Saturday and before I knew it I had five unit tests. Then I had eight. It’s Sunday and I’m up to 71 unit tests.

Writing the unit tests wasn’t all that hard. The hard part was fixing all the bugs I found!

Yup, I found multiple math errors, poor error-handling, incorrect date formatting and some bad regex that just didn’t work.

It’s amazing. I’m converted and I can’t imagine writing code in the future without writing my unit tests.

Setting up Git Pulls in Crontab

I have a small application that reads Git data and processes developer contributions based on lines of code (inserts + deletes), files edited and the number of commits each month. I wanted to automate the Git pull command so that this application would stay up to date without me having to manually run a command-line script.

My first thought was to schedule it in cron so that I didn’t have to worry about it. This is running on my development laptop — at least for now — and I knew that if I ran the “git pull” command under my username, I shouldn’t have any issues.

However, that was not the case. Every time the script was run from cron, it failed with a permission error. Running the same script by invoking it from the command line, however, executed without an issue.

But what was the permission error? Was it that Git could not be invoked? After some serious searching through Google and Stack Overflow, I determined that it was likely an SSH problem. Stack Overflow is filled with comments about using Git hooks and setting up a “bare” repository, etc. That was a lot more complicated and I resolved to just run it by hand.

A day later, though, I discussed this with one our senior developers — who has a much deeper understanding of Git. He agreed that this was an SSH issue. Together, we determined my script — when run from cron — did not have the rights to access my RSA key file, which is how I access my Git server (not GitHub).

So, we created a new RSA key just for this process using ssh-keygen and storing it in a specific directory. The key to this was to hit the enter key each time ssh-keygen asked for a password. This allows the script to pull the repos unattended.

ssh-keygen -f .git-ssh/id_rsa

Once my public key id_rsa.pub was copied to the Git server, I was then able to modify the pull command in my script to force it use the new ssh key.

ssh-agent bash -c 'ssh-add /Users/username/.git-ssh/id_rsa; git pull'

This was about a five minute process and it works perfectly.

My crontab entry looks like this:

0 9-16 * * 1-5 /Users/username/scripts/update-repos.pl  > /path/to/logs/git-perl-pull.txt 2>&1

This will run between 9am and 4pm Monday through Friday.

MySQL & Perl on OS X Mavericks

After upgrading to Mavericks, my local development environment stopped working — more specifically, Perl would no longer talk to MySQL.

Recently, I decided to figure it out.

I was getting the following error from a Perl script that was trying to talk to my database. The database was there, it was accessible from the command line, and I verified that my Perl DBI libraries were installed.

install_driver(mysql) failed: Can't load '/Library/Perl/5.16/darwin-thread-multi-2level/auto/DBD/mysql/mysql.bundle' for module DBD::mysql: dlopen(/Library/Perl/5.16/darwin-thread-multi-2level/auto/DBD/mysql/mysql.bundle, 1): Library not loaded: libmysqlclient.18.dylib
  Referenced from: /Library/Perl/5.16/darwin-thread-multi-2level/auto/DBD/mysql/mysql.bundle
  Reason: image not found at /System/Library/Perl/5.16/darwin-thread-multi-2level/DynaLoader.pm line 194.
 at (eval 21) line 3.

After some searching, I realized that Perl was trying to load MySQL, but from the wrong location. Perl expected the libmysqlclient.dylib to live at /usr/lib but Mavericks had installed it at /usr/local.

So, I created a symlink to redirect Perl to the right location.

sudo ln -s /usr/local/mysql-5.6.17-osx10.7-x86_64/lib/libmysqlclient.18.dylib /usr/lib/libmysqlclient.18.dylib

It should be noted that libmysqlclient.dylib will contain version information in the filename and Perl will expect it there. Your version is likely different than mine, so be sure to update it as needed. If you’re wondering, what version Perl is looking for, read your error message and that will tell you.