Skip navigation

…encountering new errors along the way, as well.

chad@scheherazade:pydagogical$ python3 -m ai.ants
Ant 0 is a touring machine.
Traceback (most recent call last):
  File "/usr/lib/python3.5/random.py", line 253, in choice
    i = self._randbelow(len(seq))
  File "/usr/lib/python3.5/random.py", line 230, in _randbelow
    r = getrandbits(k)          # 0 <= r < 2**k
ValueError: number of bits must be greater than zero
 
During handling of the above exception, another exception occurred:
 
Traceback (most recent call last):
  File "/usr/lib/python3.5/runpy.py", line 184, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib/python3.5/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/home/chad/kode/pydagogical/ai/ants.py", line 85, in <module>
    solver.solve()
  File "/home/chad/kode/pydagogical/ai/ants.py", line 57, in solve
    self.ant_tour(i)
  File "/home/chad/kode/pydagogical/ai/ants.py", line 41, in ant_tour
    next_city = self.get_random_next(self.antroutes[antno], current)
  File "/home/chad/kode/pydagogical/ai/ants.py", line 52, in get_random_next
    next_city = random.choice(choices[:int(len(choices) / 4)])
  File "/usr/lib/python3.5/random.py", line 255, in choice
    raise IndexError('Cannot choose from an empty sequence')
IndexError: Cannot choose from an empty sequence

Exception during an exception? Wow.

While technically not part of my 2016 Resolution, I also got this:

66th percentile on HackerRank

You may be thinking, “66th percentile! Three stars! For an Asian, your standards aren’t much.”

Well, considering that I have a full-time job and that just around this time last year I was below 20th percentile, I’m calling this a win. 😉 😉

A full GitHub year

I technically hit the year mark on January 6 but I wanted a full perfect rectangle of green so I pushed for a week more and this is what I got.

I think it’s time to erm…cash out on the things I learned doing this thing. Or spend more time thinking and less of coding; but I think, the habit can be quite hard to break.

A few more words before I go, the year mostly revolved around two projects, interestingly both a throwback from when I was just fresh out of university.

alexandria is actually a Python “port” of my earliest project on GitHub. Scare quotes on the word “port” because, by now, it hardly is a port. I wonder if the old PHP code will still run if I try to set it up today. The Python port itself, however, was started in 2015.

PyGame-Objects is my earliest attempts at seriously Python-ing. I created Snake this year which is, yeah, not very impressive but it really made me happy to try to write it as cleanly as I could, modifying the framework (which I built too, which is what PyGame Objects is all about) when needed, and maintaining backwards-compatibility with the previous games. I think some time ago (in 2013? But that feels like a lifetime now) I tried to rename it to something cooler but I stuck with the humbler name for now, and for the foreseeable future.

I cannot contain my excitement when the debug mode for PyGame Objects finally worked. Oh what joy! It felt legit even if there is much work to be done.

Pardon my seeming lack of modesty but my great takeaway here is that I write code pretty clean. They say a good rule-of-the-thumb of code cleanliness and documentation is if you can understand code you last touched three months ago. Well I last touched most of PyGame-Objects four years ago!

But I think, I overshot my intended quota of words. Goodbye now. Gotta play The Witcher 3: Wild Hunt.

Back in the day, I was really eager to work with anything you can slap an acronym on. Practice on MVCs, JDBCs, and APIs was sorely lacking in Computer Science at any level, I’d wager, but even more so in undergrad. Heck, How to Design Programs even tiered Scheme such that some library calls and language features are not available for the first several chapters. I felt that this was such a gaping hole in my employability since geeks online develop such strong feelings when an API version is deprecated.

Fortunately, my worries on employability proved baseless. No sooner than my internship did I start working on Android and its API. Then I was into a whirlwind of proprietary MVC and then some networking alphabet soup (hello, TCP, UDP, CIMD2, EMI, SMS, AT codes, ZMQ…whew). And then, in the past few months, some more API here and there. All of which has lead me to the conclusion that documentation—often overlooked, often scoffed at—is incredibly difficult to write, much less understand.

And what would make documentation “good” to begin with? In my opinion, good documentation would be

  1. Friendly to newbies with considerable skill. I add “with considerable skill” because I would not expect any reasonable documentation to start by teaching readers how to program. For a web API, let’s start with a baseline of knowing how to issue GET and POST requests, and maybe parsing JSON. And,
  2. Has a fair amount of short, self-contained, correct examples that anyone on a tight deadline can hack together something reasonably production-ready and that anyone with more time and experience can string together for something fancier. Copy-pastable examples is a huge, huge plus to this point.

(I was sorely tempted to add a sufficient, but not necessary, condition of readers being able to work without referring to StackOverflow but decided against it. Is it really reasonable to expect developers to not refer to StackOverflow, or that they can anticipate a good deal of the unique conditions in which their readers may put their libraries/services/API to use?)

I can name a handful of documents which I think will pass those two criteria. Among them,

  • Android’s documentation.
  • Most, but definitely not all, Python libraries out there.
  • Mozilla Developer Network JS and CSS is something I will find hard to live without.
  • It’s not cool to say this but the Java API docs is definitely above average.
    • And I remember that Sun’s Java tutorial—back when Sun owned Java—is a good jump-off point to the language.
  • Even less cooler to call, is CodeIgniter’s. Anyone remembers CodeIgniter? I’d have to begrudgingly give it to PHP too. Say what you want about PHP as a language but they had usable documentation back when I was actually using it.

I’m trying to come up with a list of those who don’t but I don’t want to name names, especially when documentation is so easy to change1 but, thinking about it, I think I’ve discerned a pattern: they are all, more or less, “corporate data” APIs. And cool companies are not exempt from exposing a “corporate data” API or two.

Common sins of APIs are:

  1. Being outdated. Though I’m inclined to think that frustrations which I’d bin under this label could be due to my slack as well. See I usually just Google-search whatever it is I want to do and work from what seems to be the easiest example to follow from the first page of results. Sometimes, this is StackOverflow so that lets the API writers off the hook. Sometimes, it is really the official documentation. You set things up, copy-paste the code, hit run, see things work through the logs building to that moment of anticipation when the next log should show you the data you are trying to fetch…only for your code to throw an exception. Apparently, in between the time the docs were written and now, they changed the return format of their API without it getting mentioned anywhere.
  2. Not indicating the version for which the docs were written. Slightly related to (1), I stand guilty of this too. Having mentioned my workflow above, when things don’t work, it’s become my habit to check the version for which the docs apply before going to StackOverflow.
  3. Returning unclear error messages. This is a problem that pervades programming in general; at the bare metal, things just either work or not so we created exceptions to distinguish one kind of not-working from another. But even that isn’t perfectly helpful. What do you do when the interpreter tells you it ran into a null pointer in a line of code that has several objects?2 Taken to APIs, sometimes all they tell you is that they ran into a permissions error. But what kind of permission was missing? Was it my API key? Was it permission from the user for our app to access their data? Maybe, permissions error on your OS where your endpoint tried to run a script which not even root has permission to run? Hah, which brings me to the special number in this list which is…
  4. Unnecessarily leaking your implementation to your users. This is special because there is only one (and I hope there will only be one) API I’ve worked with so far which did this. They had other fuck-ups but this is the one which made me question how exactly did my life’s choices lead me to working with them. I know we have a concept of leaky abstractions but asking your API clients to wait for 30s to act on an acknowledgement they received is just sheer incompetence, not an abstraction leaking. Do you even know how to abstract, bro?

Thankfully, if you are working with languages like Python or Javascript, introspection is dead easy which kinda works around the first two. My workarounds for those that fall into #3 has ranged from the obscure (using tcpdump on the connection and debugging on Wireshark) to the fairly standard (excessive logging and StackOverflow searching). As for four…well, thankfully, I was already serving my final 30-day notice when this detail leaked.

To be fair, I’ve had my share of designing a web API for work. I’d admit that there was a phase where our documentation wouldn’t pass my standard3 but when I left I think we were in a state that is, at least, workable, if not passing both my criteria. The title of my post could also be unfair to devs since sufficiently large companies would usually have technical writers who churn out the docs. Having technical writers, however, does not mean that devs have minimal influence on the outcome of the documentation. Based on experience, a technical writer’s job can range from just formatting/proofreading whatever the devs wrote to actually understanding the system they are documenting and actually writing most, if not all, of the documentation.

So, should devs write their own documentation? Why not. The Python libraries that pass my criteria are open-source where, I presume, devs write their own docs. The only problem—at least for most devs—with what I am espousing is that they’d actually have to learn how to write and writing effectively, technical or otherwise, requires empathy. Alas, this would be another blog post on its own.

All that said, I’m at that point in my career when, if asked to work on something you can slap an acronym on, I begin wondering when would Mangastream come around to translating and releasing their Hajime no Ippo backlog. Because best practices, bro, nothing fancy. Best. Practices.

  1. One of the things that came to my mind to call out is Facebook’s docs for setting up a lead gen endpoint. When I was working on it, all they had is a screencast walkthrough of setting up one but then months later, when I had to debug something in my implementation, I found out that they have transcribed the screencast, to my relief. The screencast, being unsearchable to begin with, is definitely not friendly to anyone with a tight deadline (I should know). Whether it is newbie-friendly or not would depend on the newbie’s preference of video over text. []
  2. You reformat your code so that there is only one object per line, heh. []
  3. At the time, the documentation wasn’t solely to blame, I think. The shape of the API then was quite convoluted for a web API that my baseline of knowing GET/POST/JSON would not be enough to work with it. []

Ever since I took it to heart to write unit tests for my code, I’ve wondered how to unit test frontend functionality. Some will say (and this I remember from my early readings on unit testing) that frontend is not meant to be unit tested but, instead, should be end-to-end tested but I respectfully disagree.

(I’d admit though, that I’ve never groked the difference between unit tests and end-to-end tests. They’re all tests to me in that they ensure my implementation is up to spec and that my changes did not break existing functionality. The last part has saved my ass so much for Chess Templar.)

I disagree because frontend code has features that lends itself well to being a unit-testable component. Among them:

  • Creating DOM objects is creating objects. You should be able to assert the properties of the created objects given parameters x and y.
  • Frontend validation. You should be able to assert how your validators behave. All the more true as your validation logic becomes more complicated.
  • It is not uncommon to have a util.js file. These are utilities, possibly used across multiple files and by multiple developers. It better be tested!

Disappointingly, Javascript has remained trapped inside browsers. Sure enough, Node and company are working to do justice on that but the fact remains that not everyone is using Node and company and so their Javascript remain trapped inside browsers.

And it seems that learning how to unit test in Javascript is largely dependent on how you use Javascript. Are you using plain old jQuery? AngularJS, maybe? For my intents and purposes, I’m on plain old jQuery.

It shouldn’t come as a surprise then that I ended up choosing QUnit as my unit testing library. The docs are easy-to-understand enough. With that, you’ll be testing your Javascript in no time!

But then comes the part of automation. The project I am using this for is, quite frankly, small in scope and it would not cost me much neurons to keep in mind to fire up the HTML page of a test-runner I got from reading QUnit’s docs every time I modify my scripts. But a good programmer is a lazy programmer. So I tried to automate that the tests run at Travis as well1.

The easiest guide I can find comes from this StackOverflow answer. The answer assumes an Ant project and the original question is even for Atlassian Bamboo. However, with a few tweaks, I got it to work with the free set-up the internets afford me.

First, you’d have to install xvfb in your environment. Xvfb is crucial for making your tests headless—I’ve actually first encountered it when trying to automate Selenium tests.

What’s fantastic with CIs (done properly) is that your code gets a fresh instance to run on everytime. Though that also means setting up (meticulously) everytime as well; this means ensuring that xvfb and other dependencies like Firefox or a MySQL instance is running before your tests are ran. To do that in Travis, I had the following in my .travis.yml:

language: python
python:
    - "2.7"
before_script: "pip install -r test-requirements.txt"
install: "pip install -r requirements.txt"
script: "nosetests --with-xcoverage && ./run_js_tests"
before_install:
    - sudo apt-get update -qq
    - sudo apt-get install -y xvfb
    - sudo apt-get install -y firefox
    - sudo apt-get install -y mysql-server
    - sudo /etc/init.d/mysql start
    - sudo apt-get install -y mysql-client
    - mysql -uroot -e "CREATE DATABASE alexandria_test;"

Notes:

  • I had to install with the the -y flag. This automatically answers “yes” to all installation-related queries.
  • I had to start mysql manually.
  • I also need to create the test database manually. A few years ago I would be very uncomfortable with the hard-coded test DB name; I would want it to get the name from my config.

Next, we’re using JS Test Driver. There are a couple of Javascript libraries JAR file in the Google Code repo I linked that you need. If you are using git (as I am) and would prefer to submodule, I had the repo ported to git here. I have not yet found the time to submodule since my goal was just to get the set-up working properly.

Having all the required libraries, all the rest are just some configuration. The main call would then be,

java -jar ../lib/JsTestDriver.jar --config jsTestDriver.conf --port 4224 --browser $FIREFOX --tests all --testOutput $OUTPUT_DIR

Where --port is as configured in jsTestDriver.conf and $FIREFOX is the path to the local Firefox installation.

Next come the actual unit tests. If you have followed thus far, you should be able to see some logs related to Javascript tests in your CI server. However, if you followed QUnit’s documentation as it stands (and be able to run your tests from an HTML page test runner), you might notice that your CI reports of 0 tests found and 0 tests ran.

This is because the QUnitAdapter library in JS Test Driver features a different organization than the actual QUnit library. I had to modify my unit tests as in this commit. But in summary:

  • Don’t refer from QUnit. QUnitAdapter provides window-level (read: global) functions that are analogous to QUnit’s. So QUnit.test becomes test and QUnit.module just becomes module.
  • Similarly, forego the asserts. A notable exception is the equality assertion. QUnit’s assert has it as equal while QUnitAdapter has it as equals.
  • beforeEach becomes setup. Self-explanatory.

I figured this out because I read the source code of QUnitTestAdapter. There might be more quirks I haven’t found out yet but these should be enough to get you to testing functionality; the unit test code might not be as idiomatic as desired but hey, it works.

I’m still far from my ideal unit testing set-up for Javascript. All I’ve managed to achieve in this post is to get the tests to run in a CI environment. Notably, test failures for Javascript do not affect the result of the build. I’d also want to get the Javascript included in the coverage reports. And, maybe, reconcile QUnitTestAdapter with the actual constructs of plain QUnit.

  1. Interesting to note that jQuery does not have CI badges on its repo and that they use Node to automate. []