Wednesday, May 30, 2012

Story: Lovely Hypocrite?


I've decided to try one of Chuck Wendig's Flash Friday challenges.  This week's challenge was to go to use a random sentence generator to generate your first or last sentence in your story.  I got "Will the company suffer the lovely hypocrite?"  I figured that I could work with that, so I wrote the following story.  I hope that you enjoy it!

---------------------------------------------------------------------------------------

"Will the company suffer the lovely hypocrite?" General Mitchell asked. It was clear from his tone that he would not suffer my presence any longer.  Asking the rest of the company showed that he was sure of their answer.  "He has defied my command and has tried to sow dissent into our ranks.  Would you keep him in our honorable company?"

The company responded with growls and many men shouting, "No!"  Their anger didn't intimidate me.  I was in the right and didn't need to fear any immediate violence from them.  The code of conduct amongst the mech companies would prevent anyone from hurting me, for now.  Instead, they would just exile me from the city to roam the wastes.  People survived out there, but just barely.

Mitchell let the growls and yells settle down before speaking again.  "It is decided.  Rex Waters, you will be exiled in the heat of the day tomorrow."  He pointed to two men who grabbed my arms.  "You two take him to his quarters and lock him in.  Stand guard until someone relieves you."

I considered fighting, but I quickly dismissed the idea.  The entirety of the mech company surrounded me and I would be quickly overwhelmed.  They would hurt me, if I started a fight.  I needed to bide my time for an opportunity to escape to present itself.

The men guided me back to my quarters.  Without a word, they pushed me inside.  One of them pulled a pistol out and held me in the corner while the other ransacked my quarters.  Further hope fled as they found my service pistol and the two backups I had hidden.  Smiling at me, they pocketed my guns and left the room.  I heard the door lock.  "At least they didn't take what little money I have," I said to myself.

Knowing that I would need as much rest as I could get, I laid down on my bed.  I must have fallen asleep, as I was awoken by voices in the hallway outside of my room.  I quietly crept close to the door and listened.

"...come to relieve you," one of the voices said.  I recognized the voice of Sergeant Clost, the left gunner of the mech I commanded.

"I doubt the general would send two of Waters' subordinates to relieve us.  Go away before we lock you up with your former commander," one of the guards replied.

Corporal Winters, my right gunner, laughed.  "That bastard is getting what he deserves.  We said as much to the general when he offered us the opportunity to push the traitor out of the gates tomorrow."

Clost chimed in, "I look forward to pushing that backstabber out into the wastes."

The four of them laughed for a moment.  The same guard said, "Welch, you wait here with Clost.  I'll go with Winters to verify that they're legit."

I heard some footsteps, then what sounded like a scuffle and two loud thumps.  A moment later, the door opened.  I saw Winters standing there smiling at me and the bodies of the guards lying in the hallway.

"Move over, Colonel," Winters said, "we need to hide these two before anyone else comes to join them in their fate."

I sidled over so that Winters and Clost could drag the guards into my quarters.  Clost said, "I don't envy the headaches these two will have in the morning."

Winters laughed and added, "Not to mention the beating they'll get from the general when he finds out about this."

They dropped the bodies unceremoniously on the floor, turned to me and saluted sharply.  I smiled for the first time since my confrontation with General Mitchell.  Returning the salute, I said, "So, you're looking forward to pushing me out of the gates?"

The two exchanged amused glances.  Clost said, "The general did offer us that chance, sir."

Winters remarked, "And we did tell him that.  I wish we could see the look on his face when he figures out what happened."

I smiled back at them and said, "Do you two have a plan, or do I have to do everything around here?"

They chuckled.  Winters said, "You are the commanding officer, sir.  We're just a couple of grunts following our commander into battle.  What are your orders, sir?"

I retrieved my weapons from the guards.  Once that was done, I said, "Let's go get our mech and show the general how strong our convictions are.  If the general thinks I'm going let him overthrow the civilian government of the city, he has another think coming."

We raced towards the armory where the mechs were stored.  Since it was night, we didn't run into anyone in the halls and the armory was deserted.  We stopped in front of my mech and I was surprised at how relieved I was to see it.  A mech soldier spends most of his time in his mech.  It was like home to me and I hadn't known if I would see it again.

We mounted up as quickly as possible, but someone came in as we were finishing our pre-mission checklist.  Winters quickly aimed the right arm of the mech and fired one 50 caliber round.  The man's torso exploded into red mist as the round tore through him.

"Well, so much for secrecy," I said as I got the mech moving.  "We'll have company soon, gents, let's get out of here."

I ran the mech through the armory doors and into the same courtyard where I had been condemned earlier.  Clost aimed his arm of the mech back towards the armory and launched a few missiles into the building.  We cheered as I directed the mech to jump the wall of the compound to the sounds of secondary explosions.  The excitement of fighting for a just cause was a welcome change to our previous role of oppressing the people of the city we were supposed to protect.

Thursday, May 24, 2012

Javascript TDD/BDD/Unit Testing


I've been doing some pretty cool stuff at work lately and I think it's time for me to share some of the cool things that we're doing.  Web development isn't anything new, I've been writing HTML since I was 12 years old, but it has changed quite a bit since I wrote my first, very simple, web pages.

Another thing that isn't new for me is Javascript, but I never really got that into it or relied on it to do anything powerful.  Since starting at Best Buy, I've really gotten good at Javascript and have realized that it is quite powerful and can do a lot of good for a website.  I've also realized that it can also do a lot of harm to a website.  One thing that a lot of people omit from Javascript development is testing.  A lot of people consider testing their scripts in the browser to be adequate for their purposes.  I disagree.  Coming from back end systems, I know that thorough testing is very important and I think that this is a component of front end systems that has been lacking across the industry.  That being said, there are ways to automatically test your Javascript without using a browser.

One of the goals of the team I'm on is to introduce an automated testing tool to test Javascript automatically when the project is built.  Our build is written using ant, which I hadn't used since college, but since it's well documented, I didn't have any trouble picking it up again.  Also, I'm using Eclipse as my IDE, so it supports ant syntax highlighting and parsing, which is very helpful.  Ant is very powerful, but since it's written like XML, it can be hard to write complicated constructs like looping and conditions, but we've made it work for us, so far.

I was put in charge of incorporating Code Quality tools into our build.  At first, this was a little overwhelming.  I was just starting to get good at Javascript development and didn't have any experience with testing tools for it, but I started doing research on the internet and quickly found some testing frameworks that I didn't think would be hard to incorporate into our build.  We settled on using Jasmine and I worked on finding a way so that we could call our spec scripts from our build.

This started the frustrating part of our journey.  The people who built Jasmine don't support the different ways to launch the tool (like from an ant build), but only the framework itself.  Okay, I can overcome this, there are some open source tools that I can use listed right on their page.  I started with Jasmine-Node since we were using Node.js for our local web server to test our pages.  I quickly realized that this wouldn't work for us since Jasmine-Node doesn't create a DOM and a lot of our Javascript relies on a DOM in one way or another.

My next attempt was to try Node-Jasmine-DOM.  It has DOM support and Jasmine integration, so I thought I was getting close.  I incorporated it in the build and got it to run in the browser, but there's an aspect to Node development that I didn't realize until it was too late.  Node makes it really easy to use other Node tools as dependencies in the tool you are building.  This is great for reuse, but dependencies are called that for a reason.  One of the dependencies that the Node-Jasmine-DOM tool used had a defect in it and that was blocking our scripts from being tested in the build.  I waited patiently for a couple of weeks after submitting the bug to the owners of the dependent tool, and there was initially some good back and forth about it for a while and someone submitted a workaround for the bug.  I was excited and tried it out on my machine, but their workaround didn't work for mem (in Mac OSX), but worked in Windows.  I went back to the forum and they had closed my defect, so I commented that the workaround didn't work for me and I needed another way to make it work for me.  Another week of waiting without a response and I decided to pursue another way to run our tests.

I started my new search by trying to find a tool that would run Javascript straight from a command-line.  I would do myself what Node-Jasmine-DOM was trying to do (create a DOM and insert Jasmine).  Enter Rhino and Env.js.  I found a blog that had done this before and I was all set.  It took me less than a day to incorporate these new tools into the build and I was immediately running our specs from the build.  At the same time that I was ecstatic to be finally done with this, I was very frustrated that I had wasted so much time trying some of these other tools.

For those curious about what exactly I did, read on.  For those who don't want the technical details, thanks for reading this far!  This next part may not be for you as it will be pretty technical.

Our test target in our ant build does a few steps to run the spec scripts.  The first step is to identify the pages that need testing and has some logic built into it for that.  The next step is to convert these pages into spec runners (example), this means that I needed to insert references to our spec.js files and the Jasmine Javascript files.  Since I wanted to test the Javascript on the page, I just copied the page, changed the extension to *.runner.html and inserted the appropriate spec and Jasmine scripts.

The next step that the build does is to get the list of runner files and run them.  I created an ant macro for this step.  The Build-Doctor guy provided the envjs.bootstrap.js file that I started with, but later customized.  His was very simple and was basically just a for loop that told Envjs to load a page.  I found that that wouldn't work for more than one runner, so I changed it a bit to reload Envjs at the beginning of the loop and then load the runner file.  I also added some console.log entries so that the build is more vocal about what it's doing.

Here's where I got a little bold and changed the Jasmine.js and Env.js files to eliminate some extra console.log calls that I didn't feel were required and I added some in a couple of places where I wanted visibility.  In the end, it looks great in the build and it creates JUnit style reports that our Jenkins CI server can interpret.

I was planning on covering the other major aspect of our build, Freemarker, but this post is getting pretty long, so I'll save that for another day.  Below are some examples of what I did in our build.

This is the macro I wrote in our ant build.
<macrodef name="runRunnerList">
 <attribute name="runnerList" />
 <sequential>
  <echo message="Running files: @{runnerList}" />
  <exec executable="java">
   <arg line="-jar ${dir.lib}/java/js.jar -opt -1 lib/javascript/envjs.bootstrap.js @{runnerList}" />
  </exec>
 </sequential>
</macrodef>
This is the results of running a spec in our build as seen in the terminal.
     [exec] Launching runner: /trunk/bin/debug/_slider/_sliderTest.runner.html
     [exec] 
     [exec] Runner Started.
     [exec] _slider : should have 100 hundred items after the method addItem is called 100 times ... 
     [exec] Passed.
     [exec] _slider : should have 99 items after the method removeItem is called ... 
     [exec] Passed.
     [exec] _slider : should have zero items after the method removeAllItems is called ... 
     [exec] Passed.
     [exec] _slider : should show slider when content extends past the width of the slider ... 
     [exec] ***FAILED***
     [exec] _slider : should hide slider when content does not extend past the width of the slider ... 
     [exec] Passed.
     [exec] _slider : should remove padding from the left side of the viewport ... 
     [exec] Passed.
     [exec] _slider : should add the class bby-slider-item-first to the first item in the slider ... 
     [exec] Passed.
     [exec] _slider : should recieve the second item out of five and the HTML should match ... 
     [exec] Passed.
     [exec] _slider: 7 of 8 passed.
     [exec] Runner Finished.
     [exec] 
     [exec] Done with runner: /trunk/bin/debug/_slider/_sliderTest.runner.html
This is one of our runner files. The highlighted parts are what the build inserts into the file.
<!DOCTYPE HTML><html lang="en"><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="../css/__common/__common.css" rel="stylesheet" type="text/css" media="all">
<link href="../css/_slider/_slider.css" rel="stylesheet" type="text/css" media="all">
<script type="text/javascript" src="../js/__common/libraries.js"></script>
<script type="text/javascript" src="../js/_slider/_slider.js"></script>
<link rel="stylesheet" type="text/css" href="../js/lib/jasmine-1.2.0/jasmine.css" />
<script src="../js/lib/jasmine-1.2.0/jasmine.js"></script>
<script src="../js/lib/jasmine-1.2.0/jasmine-html.js"></script>
<script type="text/javascript" src="../js/specs/_slider.spec.js"></script>
</head><body>
<script src="../js/lib/jasmine-dom/jasmine-dom-matchers.js"></script>
<script src="../js/lib/jasmine-dom/jasmine-dom-fixtures.js"></script>
<script src="../js/lib/jasmine.console_reporter.js"></script>
<script src="../js/lib/jasmine.junit_reporter.js"></script>
<script type="text/javascript">
$(function() {
    jasmine.getEnv().addReporter(new jasmine.JUnitXmlReporter());
    jasmine.getEnv().currentRunner_.name = "__common";
    jasmine.getEnv().execute();
})
</script></body></html>
I will note here that most of our runner files have actual content in the body. The specs for this runner insert some test content into the body before the spec is run. The scripts in the body are inserted just before the </body> tag.