Wednesday, December 15, 2010

JS Unit Testing using YUI

Ok, Selenium was a partial success that you can read about here, but it really was harder then I wanted it to be and it required a lot of setup for only a little bit of testing.  I noticed that a project that I use a lot ExtJS uses a modified version of YUI Test.  So I converted my Selenium test example to YUI Test.

My initial impression was confusion because you have to download the entire YUI 2 suite just get to get the test tools.  Also, when you download the entire suite they are many different copies of the same file in various stages of minification.  But following the documentation I boiled down exactly what I needed and threw away the rest.  I put all the code for my test here so you can follow along.

You will need the following files from the YUI archive:
  1. build/logger/assets/logger.css
  2. build/logger/logger.js
  3. build/yuiloader-dom-event/yuiloader-dom-event.js
  4. build/yuitest/assets/testlogger.css
  5. build/yuitest/yuitest.js
Create an HTML file that includes the css and js files:


The HTML will also need to instantiate the test logger and run the test runner global.  I bound the test run to a button so I could control when it ran:


Now that we have a YAHOO.tool.TestRunner we need to add a test that can be run. Instanciate a new YAHOO.tool.TestCase and add it to the TestRunner.  All a TestCase needs is a name and a bunch of functions that start with "test".  Everything else is automatic.  Below is a simplified version of the full file.



Conclusion
Though Selenium is more automated that comes at the cost of being more complicated then testing should be.  If I were a team of programmers then sure setting up and maintaining Selenium Remote controls would be a small part of the overall effort, but since I am not a team of programmers I think it is overkill.

What I really need is an easy to run, easy to write, repeatable, unit testing framework in JS.  I do the leg work on pointing my various browsers at the html and reviewing the results.  When things get big enough that I need to setup a continuous integration server, or I have a QA department, then I will give Selenium another go.  For now YUI test is the way to go.

Sunday, December 12, 2010

Dealing with Email overload

This isn't strictly software related, but a lot of us have to deal with the horror that is email.  Email is not a good solution to any problem, but it is ubiquitous so it is used for all things: personal correspondence, commit tracking, defect notification, task notification, etc...  Email is all to often used as a mechanism to pass-the-buck.

The only way to deal with this email overload is to set boundaries on email usage.  A lot of people will find these boundaries annoying, if not unworkable.  Just stick with it and lead by example.  Eventually, in a time of high stress, you will be able to get to important messages fast and they will be left floundering.

My results
I am putting the summary first in hopes that you might actually try some of these suggestions.  On average I get 50 to 200 work related emails a day.  In any given day (saturday and sunday included) I will need to respond to 5 to 10 of them.  That means that I get between 40 and 195 junk emails that pass (and should pass) my junk mail filters.

By focusing on making sure my inbox only includes import emails I have reduced my inbox to 3 to 5 message each check (and I check twice a day).  On busy days I only ever check my inbox, relying on others to contact me via a different medium if they really need me.  When there is a less busy day I go through the other inbox and deal with those messages.

At the time I am writing this (on sunday) I have 1 email in my inbox and 91 emails in my other inbox that were all sent saturday.  A quick read of the 1 email and I will have to spend 5 minutes reviewing code, but the rest can wait until monday.

Use the right messaging system
Use email for messages that do not need an immediate response.  Since there is no message size limit, make sure you use the most of it.  Write emails that are well detailed and specific.  If at any point a message can be answered with "Ok" or some other monosyllabic word then email was not the correct choice.

Use Instant Messages (IM,IRC,etc...) for conversations that need semi immediate responses, and a possible record.  Many IM packages can log conversations for later viewing, which is useful when you forget things.  There are message length and formatting restrictions so this forces the messages to be brief and specific.

Use Phone, Skype, or face to face contact when a response is needed immediately.

Use Twitter, or some other global message posting service to track commits, continuous integration fails, defects, etc...

Use a wiki, or blog to track generic instructions or documentation.

Check email twice a day (only)
The easiest way to train people not to use email as a crutch is not use it as one yourself.  Only check email twice a day, and give a concerted effort to reduce that to once a day within a month, and once a week within 6 months.  Setup the other messaging systems so that email is used only for what it needs to be.  And when people step out of line, correct them.

Email should not be the first thing that you check in the morning, as you should not be working out of email.  It should also not be the last thing you check as it will disrupt your already stressful commute/home life.  Instead check email 2 hours after the start of the day, and 2 hours before the end of the day.  If you work a 9-to-5 that means once at 11am and once at 3pm.

The day you start doing this, tell the people that send you the most email and the ones that you will most affect by the change, and no one else.  You are not trying to be sneaky, but if you blast an email to everyone then you are going to make it a big deal; which it is not.  The others will learn over time.

When someone tells you that you need to check your email and read their message do it, but only check their email, ignore all other messages.

Don't use Inbox as an archive
Once you are finished reading an email, either deal with the email and delete it or archive it.  Create a separate archive folder and move emails there if you need to save them.  Your goal is aways to reduce the inbox to zero

Create an other inbox
Create a filter that will dump any messages where you are not the direct recipient into a different folder.  This should be the first filter you create, but the last filter that is applied to any message.  Create as many other filters and folders as you can to move useless messages round.  The goal is to remove any message that you do not need to act on so that what is left is just what is important.  The trash can is a good folder to dump things that are truly useless.

Use the server's filtering mechanism
When possible have server do all the filtering that way you can use multiple email clients and will not be dependent on leaving an email client on.  All Exchange servers and many online email services can do server filtering.  When using Outlook, be careful, the ease of creating filters is sometimes offset by the fact that it lies about what filters can be saved to the server.  Though harder, since MS didn't spend much time on the server-side features of Exchange, it is better to build the filters on the server directly.

Reduce the inbox to zero (in one sitting)
The goal is always to reduce your inbox to zero.  Once all the filters are in place, the only thing left to actually deal with all the important emails (at least that is the hope).  When dealing with email decide if the email should be dealt with, deferred, or archived.

If time is really an issue then find the messages to archive and defer first, and move them.  That way what is left is just the stuff to deal with now.

Sunday, December 5, 2010

How to be a bad boss

Being a boss is a complicated thing. It is your job to get people to do things, sometimes things they do not want to do. And it is especially complicated in the software industry, where it is like herding cats.

I see a lot of posts on how to be a good boss, but the problem there is that they often forget to mention the things that can and will immediately erode any success you might have had. I am going to assume that as a reader you strive to be a person who others are willing to follow.

Nobody is perfect, so you will probably have done at least one of these things in the past.  Or you do then without even knowing.  Now is your chance to stop, and be a constructive boss who people want to work for.

Be smarmy

Yep, this is number one. Smarmy people are falsely friendly (think used car dealers).  Notice I did not say do not "be mean." As a boss sometimes you will need to be mean, or at least not very nice. And even that should be kept to a minimum, but it is never OK to be smarmy. All it does is make people uncomfortable confiding in you, which means they will either find better employment (if they can) or they will sabotage you.

Here are some examples of what I mean by smarmy:
  • Suggest that a problem can be solved by the employee working overtime
  • Using scrum (or any general meeting) to point out an employee's failure
  • Joke about firing an employee
  • Make any sarcastic comment about an employee in the presence of others
  • Only talking to an employee when you need them to do something (i.e., I am only talking to you because I want something)

Some ways to tell that you have already failed at this:
  • All laughter stops when you enter the room
  • Conversations between you and an employee die quickly
  • Employees no longer tell you about issues they are having

Be a hypocrite

A hypocrite is someone who says one thing and thinks or does another.  It can be as overt as being prejudiced (racist, sexist, etc...) or as covert as being passive aggressive.  Being a hypocrite is risky because when other people find out, you are just being deceitful, and no one wants to deal with that.

One example is saying that code needs to be high quality but not leaving time for testing.  Overtly this often resembles explicitly adding a testing phase at the end of coding and then cutting it if coding goes long.  Covertly this is often assuming that testing is done as part of coding, but scoffing at longer estimates.  Speed and quality have a tenuous relationship.  Something done slowly may or may not be of quality, but something quickly is almost never of quality.

The best way not to be a hypocrite is not to bring your values and prejudices into the equation.  To do this though you have to understand what your values and prejudices are.  In the case of the no testing, quality is explicitly stated as the important part, but speed is implicitly stated as the important factor.  More specifically speed at the cost of quality is stated as the import factor.  To avoid this, it is important to explicitly state the importance of all three tenets of the project triangle: that way you avoid the embarrassing case where one tenet goes to 0 unintentionally.  See: Project Triangle.

Be arrogant

I am not talking about being hard headed or stubborn.  I am talking about being truly arrogant.  Stubborn people will listen to reason, assuming the opposing argument is good enough; arrogant people cannot be directly convinced.  There are two forms of arrogance to watch out for: arrogance of idea, and arrogance of presenter.  Arrogance of idea is simply dismissing an idea because it is in direct conflict with your internal ideas or values.  Arrogance of presenter is rejecting an idea because of who presented it.

Two engineers approach you with different solutions to the problem of releasing on time: one says to keep the feature set and stop doing unit testing, and the other says reduce the feature set but keep the unit testing.  Which do you choose?  If you choose "keep the feature set" then you wrong.  If you choose "keep the unit testing" you are also wrong.  If you chose either (based on only the information provided) then the choice you made was based on you internal values only and not based on the problem being presented.

In the context of work the truth is that new hires probably know more about a given framework than you, and certainly will have a different perspective on how things should be done.  They are probably offering you this knowledge, because they have already encountered the problem you are now seeing and have found an appropriate solution.  It is tempting to dismiss this simply because a new hire presented it and they don't know the full business impact of their suggestion.  But ask yourself: if the system architect presented you with this idea would you accept it?  If yes, then you are suffering from arrogance of presenter and should tread lightly.

I suggest instead that you judge an idea (never a presenter) on its merits in the context of only the problem (never on facts you assume to be true).  And make sure you are consciously and actively judging the idea, and you are not adding your own problem or values.

Offer post hoc rewards

A post hoc reward is a reward given after work is complete.  In physical work the effects of post hoc rewards are well known and lead to better results, but in knowledge work offering post hoc rewards has a distracting effect. Work will take longer and be of lower quality. It will make employees very good at performing work that maximises their incentives, and not at developing a quality product.  Be aware that offering reward for work done defines a tangible value for that work, which may demoralize an employee who feels under compensated as a result.

http://www.youtube.com/watch?v=u6XAPnuFjJc

Intrinsic rewards can and should be used.  These are things that are given universally and without reservation.  Basic examples would be vacation, and health benefits.  Other examples would be a free day to work on any project the employee wanted, or free soda/tea/coffee.  These intrinsic benefits help endear you and the company to the employee.

Accept estimates less than 4 hours

This may only be true in software, but tasks never take less than 4 hours.  A task is really an atomic complete chunk of work, so to be considered complete it must be coded, tested, reviewed, and committed.  However, some employees will claim they finish tasks sooner.  Often these people are cutting corners (not testing, or not getting a review) or they are doing a bunch of tasks that should have logically been considered one task.

Either way they are playing a game with the numbers to get their counts higher, which means that you are probably rewarding over aggressive estimates, and have a huge defect backlog.  Well done!

Assume research is intrinsic

I have seen this bite so many bosses, where they say something like "tasks cannot take longer then 4 days."  The problem is that now you have employees trying to split tasks that have little or no real research done.  So when it comes time to implement you have a bunch of small tasks that are too small to warrant research, but no real clear direction because no real research was done.

Estimates of several weeks or months are fine early in the process.  But enough time needs to be given to investigate feasibility prior to high level scoping.  Prior to implementation, time should be given to research an implementation and split the tasks out.  All of this time should have been blocked in as a single unit during high level scoping.

Require meetings

Meetings cost time and money.  And in addition to the meeting itself there is time before the meeting where people ramp down, and time after the meeting when people need to ramp back up again.  Both ramping phases are about 10 minutes each.

To monetize this for you, let's say you have 12 employees going to a meeting, and on average they make $24 an hour, and the meeting is 15 minutes (a scrum).  The total chunk of wasted time is 35 minutes or about $14 per employee.  For the company that means you wasted $168.  And that does not include any prep time employees had to take.

In general, meetings need to be kept to a minimum and kept on track because they will end up being the single most costly event both in terms of money and productivity.

Watch your employees work

Nobody is comfortable being scrutinized.  Do not set up your office so that you are looking into your employees' cubes, and don't wonder around aimlessly, and never under any circumstances hover.  By doing this you are showing your employees that the most important thing is to look busy (a function of the keyboard and finger), not to solve problems (a function of the brain).  At the point where your employees feel scrutinized they will work just hard enough to not get fired, and will partake in CYA games.

The best example is Office Space the movie.  Little more needs to be said.

Saturday, December 4, 2010

GIT with SVN

Normally, I would just use GIT without a bridge to another control system, but many companies use SVN. There are just so many benefits to using GIT that, for me, I am going to use it if there is a bridge to repository type the company uses. I certainly don't hate SVN or CVS or Perforce, but GIT allows me to work the way that I know I am most productive; which is commit early, commit often.

What I mean by commit early, commit often is that I commit even if I only have part of the solution.  As I find the other parts of the solution I commit those as well.  That way when I am 2 or 3 days into a fix I already have the commit messages saved in GIT, so I don't have to remember what I did for those 2 or 3 days.  When the solution is shippable only then do I push it up to the company's repository.

Benefits of GIT include:
  1. Being able to share non production ready code (Peer to Peer)
  2. Being able to have many local branches
  3. Being able to logically group commits (via local branches) and push all at once
  4. Fantastic branch switching/merging
    1. Rarely will you ever have to fix a merge conflict yourself
  5. Rebase as well as merge
    1. Rebase is SVNs style of linear commits
    2. Merge is non-linear and tries to keep commits sequentially ordered by date. So if two branches are merged and both were actively worked on then the commits are intermixed. (makes a lot more sense in practice then in writing)

With GIT's power comes a little bit more complexity, and here I will detail the method that I have developed over months of fits and starts. That way you can experience the benefits of using GIT for day to day work, but still use SVN when dealing with corporate.

Settings up the SVN Bridge
You can have GIT manage an entire SVN repository, branches and all.  However, for GIT to do this it must checkout every revision of the SVN repo.  This can be very painful when there are a lot of commits.  Instead I recommend only managing a single branch starting a specific revision near HEAD.  You will lose history older then that revision, but it does save a lot of time for large SVN repositories.

For the below example I am going to assume we have a standard SVN repository at http://example.com/svn, the latest revision is 400, and the SVN username is test.

Find the latest revision of the repository:
svn log http://example.com/svn/trunk | head

The latest revision will start with an "r" and be within the first 5 lines.

Setting up a git repo:
git svn init --username=test http://example.com/svn/trunk dev
git svn fetch -r 400

Now you have a local GIT repo in dev that is synced to SVN trunk at revision 400.  And when you git svn dcommit the user test will be used.

Always work in a branch

In my company before anything is allowed to be checked into SVN it must go through a peer review. In any given day I might work on 2 or 3 bugs/tasks. For each, I create a GIT branch with the bug/task ID and work there. When I am done I use git log -p to list the diffs that I submit for review. Then I move on to the next item, while the fix is being reviewed. When the first bug/task is reviewed and accepted I jump back to master, rebase it, jump to the branch, rebase master, jump back to master and merge the branch, and finally svn dcommit everything. After I mark the bug/task complete I also delete the branch.  If the code is not accepted then I still have a branch where I can make the required corrections and repeat the process.

It might sound complicated, but it really isn't.  The only reason for all this rebasing is so that GIT's native merge tools deal with SVN merge conflicts.  I am not sure why, but they are far better then what the SVN bridge can do, and will ultimately lead to few headaches for you.

In code it looks like:
git> git svn rebase
git> git checkout -b task1
... work on task 1
git> git log -p -n X > task1.diff
... create diff of all (X) changes needed for task1
... email the diff for review
git> git checkout master
git> git svn rebase
git> git checkout -b task2
... work on task 2
... when task 1 is approved commit what you have for task 2 and dcommit task1
... return to task 2 when task 1 is committed

This style also works well if your boss comes over at the 11th hour and assignes you a new emergency assignment. When you are done with the emergency switching gears is as easy as switching branches.

DCommitting your changes

As states above I use the checkout, rebase, checkout, rebase, checkout, merge, dcommit style. This seems cumbersome until you understand the purpose.

From any branch always checkout into master. This allows master to stay pure of your changes and makes its less likely that git svn will fail.

Once master is up-to-date checkout the branch again and rebase the master changes into the branch. Fixing any rebase conflicts there might be. By fixing them on the branch we keep master clean so we are using git's rebase/merge capabilities, not the SVN bridge's. There are times this step can be skipped, but once you have to deal with your first rebase conflict from the bridge you will wish you had branched.

Now that the branch holds the latest code to be dcommitted to SVN: checkout master, merge the branch, and dcommit master. You could rebase the changes from the branch if you prefer, it really makes no difference because your changes are on top of SVN now either way. Once done all of master's log messages will be rewritten to what is in SVN.

All together it looks like this:
git> git checkout master
git> git svn rebase
git> git checkout task1
git> git rebase master
... SVN needs your changes to be rebased so rebase master
... by rebasing onto to a branch it is easier to deal with rebase failures
... fix any rebase issues
git> git checkout master
git> git merge task1
... could merge or rebase, doesn't matter here
git> git svn dcommit
... mark the task closed
git> git brach -D task1
... svn doesn't always mark the branch merged properly so use -D instead of -d

Pro Tips

Different user names

Use a different username for SVN and GIT. That way it is easy to see in the log what is committed to SVN since the bridge will rewrite the commit log from what SVN says.

  • For SVN I use jkamenik.
  • For GIT I use jkamenik at gmail dot com.

Commits that are in SVN also have the SVN revision number in the log message, but I find it easier to use usernames since it is at the top of the log message.

Setup Aliases

Git allows more commands to be added via aliases.  An alias can be a shortening of a git command: st = status.  Or it can be a shell command that git will execute test = !sh -c 'echo "it works!"' (notice the leading !).

Here is the alias part of my ~/.gitconfig file looks like:
[alias]
  # Old SVN aliases
  ci = commit
  co = checkout
  st = status
  stat = status
  # stuff I find useful
  br = branch
  df = diff
  rm-all = !git st | grep deleted | awk '{print $3}' | xargs git rm
  add-all = !git st | grep modified | awk '{print $3}' | xargs git add
  st-br = "!f(){ git co master && git svn rebase && git co -b $1 }; `f`"
  up-br = "!f(){ git co master && git svn rebase && git co $1 }; `f`"
  co-br = "!f(){ git up-br $1 && git co master && git merge $1 && git svn dcommit }; `f`"

Notice that st-br, up-br, and co-br are basically all the set of commands I noted above in single command style.

Stashing changes

The stash is a hidden place that git can keep changes that are not yet ready to commit. This is very useful if you get switched to another task and really don't have time to fully vet a change on the current task. You can stash the outstanding change and later replay them.

git stash keeps a queue of changes so you can stash more then one thing, but you can only replay them top down.

git> git stash
... hides all modified files
git> git stash list
... lists all stashes
git> git stash apply
... applies the top stash, but does not remove it
git> git stash pop
... applies the top stash, and remove it

Resources
  • GIT <-> SVN workflow: http://www.biostat.jhsph.edu/~rpeng/biostat776/workflow.html
  • Effectively using GIT with SVN: http://www.viget.com/extend/effectively-using-git-with-subversion/