Learning From Other People’s Code (And Also Breaking It…)
A week or two ago I was asked if I knew how to make the test package used to see if our code meets the requirements of labs, make a noise if all the tests are successfully passed. I quickly replied, “uhhh, I dunno…” and that was that.
Cut to 1am that night and I can’t sleep. I start wondering how hard it would be to actually make the tests make a noise. So, I grabbed my laptop and started.
I quickly realized I actually didn’t know what was even running the tests. I figured out it was gem, the “learn-co” gem. Cool — but where are my gems stored? In the home directory in a directory named “.rvm/”.
From there it took some digging through directories. Eventually I found the gem folder for the version of of Ruby I am using (2.3.4). Turns out, there is the main “learn-co” gem and 10 other “learn-*” libraries that are used by the main one. At this point I just randomly started looking in the directories.
Not entirely randomly — there were two directories that jumped out: “learn-submit” and “learn-test”. I figured that the files I was looking for were most likely in on of these two. The answer was the “learn-test” directory.
Above you can see that there are many files to look through. At this point I had to try and figure out how this was designed and how it works. This is first takeaway from this rabbit hole I went down. You can learn a lot from other people’s projects and code. When it’s something like a gem, you can see what a public project actually looks like. How it should be structured, the flow of information, and about a hundred other random things. The goal was not to write my own new package but rather to amend an already existing one. So it was not my design I was working with — and that’s important. The thinking changes from “how should I design something” to “how was this designed and how can work within those parameters.”
After crawling around the code I finally found something promising — a runner.rb file.
I’m not going to explain how this all works (partly because I don’t know it all because I didn’t need to). The short version is the runner runs the appropriate test (a strategy) which creates a nice little hash.
On line 59 you can see this:
failure_count: output ? output[:summary][:failure_count] : 1
This will represent the number of tests that failed. So — when this is equal to zero, the computer should make noise.
Originally I crammed my code into the exact location I needed the new functionality. After it worked I turned it into a method and called it in the correct location:
Turns out it was pretty simple. First — check if the failure count equals zero. Based on that, say one of two options. In Ruby, if you put code in back back-ticks (``), it will run it in the terminal. The terminal accepts that command “say” and will use the Mac’s native text-to-audio feature and actually say the words that follow. Good stuff.
Turns out it is really annoying to have the test make a sound every time it is run. So I decided to learn about using flags in the terminal. That led me to this file:
This is when I learned about the “OptionParser” class in ruby. From the docs:
OptionParser is a class for command-line option analysis.
I just mimicked the format of the file and created the flags “-a” and “ — audio”. Now when the test is run, only if the flag is passed will audio play.
And that’s it really. The last thing I did was add a short description of the functional to help menu so people could learn about it.
I would recommend attempting similar projects. A lot can be learned fro working with other peoples projects and code. It is an entirely different experience. It is more about being comfortable reading code and discovering the design and intent of someone else. It may also involve “breaking” the gem and having to fix it…