Programming Practice and Mentorship with Exercism.io

Last night I met up with a new friend for a JavaScript study session. Like almost everyone I socialize with now, I met her through my Learn to Code LA meetup group. I started it just about 3 months ago, and it’s already introduced me to a whole new world of technologies, careers, and philosophies that I had never even heard of before!

Anyway, my friend introduced me to exercism.io, a tool that helps you improve your skills through “crowd-sourced mentorship”, created by Katrina Owen. (Actually, I’m not entirely sure what it is, because their website doesn’t explain it that well. Hopefully it will make sense once I start using it.)

##Setting up Exercism.io on Windows

I logged in using my GitHub account. Easy enough. The welcome page explains how it works:

  • “Fetch the current exercises using the command-line client.”
  • “Write code using your usual tools. Make the tests pass.”
  • “Submit the code to the website. Other people who have completed the same assignment provide a code review, ask questions, and discuss trade-offs with you.”

Sounds good to me! And their list of GitHub issues indicates a pretty active community.

So I need to install the command line interface (CLI), which I heard can be trickier on Windows, so I’m feeling a little bit nervous right now. Luckily, they have detailed instructions for Windows. So, first I need to check if I’m on a 32-bit or a 64-bit version of Windows. (I don’t even know exactly what the difference is, to be honest!) But it looks like I’m on 64-bit Windows.

Downloading the latest release for 64-bit Windows…

Copying the executable file from the zip file into a new folder…

Now, what’s all this stuff about adding it to my PATH? Like I’ve mentioned before, I’m still very new to using the command line, so I thought I should read up on this a bit first.

From Wikipedia:

“PATH is an environment variable on Unix-like operating systems, DOS, OS/2, and Microsoft Windows, specifying a set of directories where executable programs are located.”

That helps a little, but I sense a very deep rabbit hole here… I don’t want to dive into learning all about the guts of operating systems just yet. Well, I do want to, but I need to stay focused on the basics first!

Following their instructions, I’m backing up my PATH variable by typing this into the command prompt:

C:\Users\MyName> PATH > yyyy-mm-dd_PATH_backup.txt

Oh wait, I’m stupid! I don’t type the first part, haha. Oops. And I obviously need to replace the date with the actual date, so I type this:

PATH > 2015-05-06_PATH_backup.txt

Seems to have worked; I have a new text file in my users folder. I opened it up, and it seems to contain a list of program locations, including where I installed Python and Ruby a while back. Cool!

The instructions warn me that if I skip a step, I could break my computer or something. Better be careful! Oh, actually, this is super simple, basically just a copy-paste into a Systems window. Done!

Now, let’s see if it worked…

The Exercism.io command line interface

Success! And I didn’t even break anything! OK, that was actually very easy. Hearing from multiple people that installing stuff like this on Windows is “a nightmare” just made me really nervous about it. I probably wouldn’t have written about the process in detail if I knew it would be this straightforward.

Next, I configure exercism using my API key from their website:

$ exercism configure --key=YOUR_API_KEY

(I did learn a while back that you’re not supposed to type the $, only the other stuff. lolz.)

Next, I need to follow the instructions for JavaScript and install Node.js. Oh wait, apparently I already have it installed!

So now I just need to install this jasmine-node thing, which is apparently a Node.js plugin for Jasmine, which is apparently a JavaScript testing framework. And apparently I can install what I need just by typing this into the command line:

$ npm install jasmine-node -g

Yay, I think it worked! So I guess this means that I should be able to run test files using that Jasmine framework now. But first, I need to actually download the files for exercism’s practice problems. It looks like all I have to do is this:

$ exercism fetch javascript

Cool! It created a new folder for me. I’ll use the cd command (which stands for “change directory”) to move into exercism/javascript/bob. In there I now have a README file containing instructions, and two JavaScript files: bob.js and bob_test.spec.js, which I assume is the file for the test framework.

The JavaScript instructions say that to run that test file using the Jasmine framework, I just have to type this:

$ jasmine-node bob_test.spec.js

Hmm, it looks like it’s broken…. Oh right, but that’s the whole point! I’m supposed to write some code in order to pass the tests. So of course it says the test failed:

exercism Jasmine test

OK, so I need to make the tests pass. How do I do that? What are the tests? Why is it set up this way? And who in the world is Bob?!

##Test-Driven Development (TDD)

Whenever you don’t know what something is, go to Wikipedia!

Test-driven development (TDD) is a software development process that relies on the repetition of a very short development cycle: first the developer writes an (initially failing) automated test case that defines a desired improvement or new function, then produces the minimum amount of code to pass that test, and finally refactors the new code to acceptable standards.”

I also like this description from An Introduction to Test Driven Development:

“Not only does this process prove that the emerging code correctly satisfies tests (essentially that the code is fit for purpose) but it aids developers in thinking about the design of the code they write.”
“In addition, tests by their very nature, provide valuable documentation. The tests grow to form a catalogue of how the software should behave…”

In fact, he describes TDD as a way to fight “entropy” in code – the way little inconsistencies and moments of laziness add up over time to create “spaghetti code”. (I didn’t know was a real term! That just tickles me, haha.)

Anyway, I just spent some time searching the interwebz for a mroe detailed and beginner-friendly guide to test-driven development, but so far I haven’t found anything really good. (If you know of any, let me know!)

But I did find some other resources that look useful but seem too complicated for me right now, so I’ll dump them here and come back to them later:

I guess I’ll just dive right into the first practice problem from exercism.io and learn about this whole TDD philosophy as I go along.

##First Attempt at Making a Test Pass

The following notes won’t make any sense unless you’re following along with the exercise files! You can see the files on their website here:

OK, here we go! So I don’t know why this works, but I can infer from the code that bob_test.spec.js is testing the function bob.hey() and expecting the result to be 'Whatever.' when given the input 'Tom-ay-to, tom-aaaah-to.':

it("stating something", function() {
    var result = bob.hey('Tom-ay-to, tom-aaaah-to.');
    expect(result).toEqual('Whatever.');
  });

And then in bob.js, I’m supposed to define the bob.hey() function so that it returns the expected result when given that input:

Bob.prototype.hey = function(input) {
	// Here's the code I added to pass the first test:
    return 'Whatever.';
};

This is the laziest (and most efficient) way to pass the first test, because it gives the expected result of 'Whatever.' regardless of what the input is. It will probably fail the other 16 tests, but let’s see if it worked for the first test. I’ll run the test again:

$ jasmine-node bob_test.spec.js

And… success!

First Exercism.io test passed!

Now, following the instructions to submit an exercise, I’ll type this:

$ exercism submit bob.js

Cool, it says my submission can be viewed online here! I added a comment explaining that my solution is the simplest, most efficient way to pass the first test.

First Exercism.io submission

##Onto the next test!

I realized I didn’t know how to move onto the next test, so I did a little digging. This page gave me a clue (though I wish they made it more obvious!):

“Some of the languages use skipped or pending tests in order to simulate the Test-Driven Development (TDD) process.”
“In these languages, only the first test will be active. Once you write enough code to get that test passing, you’ll need to open up the test suite and edit it to remove the skip to activate the next test.”

And how do I “remove the skip to activate the next test”, I wonder? A little Googling took me to Jasmine’s introduction page, which revealed that the it() function I saw in bob_test.spec.js is used for active tests, and the xit() function is used for pending or inactive tests. That’s the key I was looking for! I took a look in bob_test.spec.js again and sure enough, the other 16 tests all use xit(). So all I have to do is remove the x and I should be able to run the other tests one at a time or all at once.

Second Exercism.io test failed

Cool, now I’m onto the second test. But this could take forever if I try to make the code pass one test at a time! Looking ahead at the other tests and the README file, the pattern seems to be something like this:

  • Shouting: If the input is in all-caps, the result should be ‘Whoa, chill out!’
  • Questions: If the input ends in a question mark and it doesn’t meet the criteria for “shouting” listed above, the result should be ‘Sure.’
  • Silence: If the input is empty or contains nothing but spaces, the result should be ‘Fine. Be that way!’
  • Whatevs: For everything else, the result should be ‘Whatever.’

I’m going to let my ideas percolate while I walk to tonight’s meetup group, and then I hope to work on the problem with a buddy or two while I’m there. I should be able to solve this before bedtime, I think!

##Manipulating Strings in JavaScript

This is a new little challenge for me. I like this! OK, so off the top of my head, I don’t know how to determine if every letter in a string is capitalized. I also don’t know how to determine if a character is a letter or a number or a special character. Time to search through my favorite JavaScript reference!

Useful stuff I’ve found so far:

Luckily for me, toUpperCase() also works on special characters that represent letters with accent marks! So this should work for all 17 tests in this exercise, some of which contain letters with umlauts.

So I think it should look something like this:

if( input == input.toUpperCase() ) {
   // If all letter characters are uppercase, give the shouting result       
   return 'Whoa, chill out!';
}

Now, for identifying questions, I just need to check if the last character in the string is a question mark. For that, I could use the charAt() method or substring() method. I’m not sure if it matters which I use, but it seems like charAt() is simpler, so I’ll go with that:

if( input.charAt(input.length - 1) == '?' ) {
   return 'Sure.';
}

And now fo identifying silence, I think that trim() method will do the trick! Something like this:

if( input.trim() == '' ) {
   return 'Fine. Be that way!';
}

Now I’ll throw it all together and see if it passes all the tests! Here’s my code:

// silence: if input is empty or contains nothing but empty characters

if( input.trim() == '' ) {
   return 'Fine. Be that way!';
// shouting: if all letter characters are uppercase
} else if ( input == input.toUpperCase() ) {
   return 'Whoa, chill out!';    
// question: if last character ends in '?'
} else if( input.charAt(input.length - 1) == '?' ) {
   return 'Sure.';
// default response for a teenager:
} else {
    return 'Whatever.';
}

And here’s the result:

Exercism.io Bob exercise

Oh right, numbers! There are two tests for inputs with no letters: '1, 2, 3' which should have the result 'Whatever.', and '4?', which should have the result 'Sure.' I guess I need to check if the string contains letters, because these special cases need to be handled by different rules.

Regular expressions to the rescue! I remember using regular expressions with PHP several years ago, so I know that you can use them to check for certain patterns within strings. A quick review of Eloquent JavaScript and the MDN JavaScript reference showed me what I need to change for my shouting condition:

// shouting: if all characters are uppercase and the string contains letters
else if( input == input.toUpperCase() && input /[a-zA-Z]/.test(input) ) {
   return 'Whoa, chill out!';
}

Let’s see if that worked…

Exercism.io Bob exercise completed!

BOOYEAH! I win! Haha, OK, it’s almost my bedtime so I’m going to submit my solution and see if I get any feedback on it here. Goodnight!