Setting up MaxCDN with a WordPress blog hosted on Digital Ocean with a custom domain

This guide was written after I completed the process of hooking up MaxCDN to my Digital Ocean hosted WordPress blog.


This wasn’t a straightforward process, partially due to my own errors and partially because I was using WP Super Cache which I’m pretty sure just doesn’t cooperate with MaxCDN for reasons I may never understand. However, I now have it working so here’s my guide to everything I did.

Why I wanted a CDN: To speed up my top money-making property, which is also my slowest because it’s got long articles and lots of images.

I chose MaxCDN because it seemed to have a lot of good reviews and at about $10/month was reasonably priced.

Setting up MaxCDN with W3 Total Cache and a custom CNAME on Digital Ocean

I signed up and was disappointed to see that the URL MaxCDN gave me by default included the business name I used when I signed up. I wanted, but by default MaxCDN gave me MaxCDN calls this the “branded domain” and you can use it as-is, but I would guess most people want to customize it.

My business name and my website name are not the same and I didn’t want to expose the former in the latter. (They don’t tell you they’ll use your business name this way when you sign up, nor do they let you change it once you opened your account. Ugh.)

Fortunately, you can set up a custom domain and use that instead, and my steps below include that process.

Step 0: Set up a pull zone. MaxCDN has good documentation on pull zones.

Step 1: Enter your custom domain into the pull zone settings. Go to Pull Zones > Settings and fill in the Custom Domains field with (or, or whatever you prefer. The important thing is that all three parts of the url are present.)

Step 2: Get into Digital Ocean’s record management. Inside Digital Ocean’s droplet management page, go to Networking and then go to Domains. Click the magnifying glass next to the domain you’re adding this CDN to to get into its records. More help adding/editing domain records in Digital Ocean.

Look in Networking, Domains

Step 3: Add a CNAME record to your droplet’s domain.  If you want, fill the form out like this:

  • Enter Name: cdn1
  • Enter hostname: (the “branded” domain that Digital Ocean gave you by default)

Be sure to click the Create CNAME Record button to actually add it to the list of records.


Step 4: Wait about 20 minutes for it to propagate. 

You can watch it propagate here:

Assuming nothing else is conflicting (you didn’t leave your DNS hooked up to CloudFlare like I did, you don’t have a competing record like I did, etc), this should happen in 20 minutes or less.

Step 5: Now you can hook it up in your WordPress caching plugin! MaxCDN has docs for setting up MaxCDN with many different WordPress caching plugins here.

At first, I was using WP Super Cache and every time I turned on the CDN feature my site’s styling and images disappeared. I fought with this for a while, got good and frustrated, then tried W3 Total Cache like MaxCDN suggests and WOW – it was like night and day. I followed MaxCDN’s tutorial and basically, it just worked. Be sure to whitelist your site’s IP (go into Terminal or command prompt and ping to get your site’s IP if you don’t know it, or look in Digital Ocean’s droplet list).

If you’re having a problem with WP Super Cache making your styles and images disappear with MaxCDN, try W3 Total Cache instead.

Step 6: Verify it works by loading your site

If everything’s working, you should be able to load your site ( at its usual url (not the cdn url) and look in the network tab of your browser to see responses coming in from the CDN url (

Fast way to check: right click any image on your site and view it in another tab. Its url should be your cdn’s url.

If you don’t have any images, you can see this in Chrome by right clicking to Inspect and then click over to the Network tab before loading your site. Hover over some resources (like .css resource) and you should see

You should also start to see improvements to your page’s load time immediately.

If you don’t see the changes right away: While the changeover was observable right away on the computer I was working on, it wasn’t on my laptop. The cause seems to be the computer’s own DNS settings. By switching my laptop’s DNS settings to Google’s, I was able to see the most up-to-date (ie: not cached) version of the website.

How to use Google’s public DNS on your Mac or Windows machine:

(Alternatively, waiting a while – up to a day – should resolve it with no changes to your computer.)

Pingdom results, before and after MaxCDN

Here’s a couple of “before” load times on my website, taken less than a minute apart and both from New York City. The thing I often notice on Pingdom’s Website Speed Test is how much variance there can be in load time across multiple tests when all other factors remain the same (location testing from, time of day, etc).

Site speed: before

Here, there’s a huge difference in load time just on these two “before” tests.



The kind of extreme difference in load time seen above is why I like to run several Pingdom tests when collecting my “before” data before making a change that I think should effect load time. Here’s another test, this one from San Jose, California.


Site speed: after

Whoo! Look at that, down to <2 seconds since turning on MaxCDN:


Here’s an even faster one, best one I saw in my several tests:


And one from San Jose:


So far I like MaxCDN. Their online support is very responsive. I sent a detailed plea for help on a Sunday afternoon in the U.S. and had a (reasonably) customized response within an hour. Their documentation is plentiful and thorough. They include many examples and their screenshots are up-to-date with their current interface.

The real test will be in seeing if getting the site speed down to ~2 seconds has any noticeable effect on the site’s Google rank and total conversions (sales).

CDN Traffic Boost?

Totally unscientific study here, but my site’s traffic pulled out of a slump as soon as my CDN hookup went live. (March 17 is just beginning as I post this update.)


Relevant MaxCDN docs and tools:

Ember 2: Calling an action from a checkbox in Ember 2.0 three different ways

I recently implemented a checkbox in an Ember 2.0 project that, when checked/unchecked, would call an action and change some properties.

Searching the web reveals many different approaches to this problem, some of which (depending on your project’s needs and stack) may be more suitable for you than others.

The first time I needed a checkbox to call an action in Ember, I was just building a quick ‘n dirty prototype and I wanted to keep things simple and skip observers, components, etc., which I was able to do with some basic HTML and an Ember controller.

Simple Ember checkbox HTML/JS solution

Here’s the simplest implementation of an Ember checkbox calling an action I can come up with. It’s just HTML and JavaScript.

See it working in this JSFiddle


<input type="checkbox" 
 {{action "toggleCheckBox" on="change"}} 


setupController: function() {
 this.controller.set('toggleChecked', true);
actions: {
 toggleCheckBox: function() {
 this.controller.set('toggleChecked', !this.controller.get('toggleChecked'));

Ember checkbox as a component

Ember offers an {{input }} component that you can now hook up to actions (that apparently wasn’t true in earlier versions of Ember, but it’s true as of this writing which uses Ember 2.0).

The input component implementation looks like this:

{{input type="checkbox"
      change=(action togglePolicyRead)}}

To register the action with the controller, you’ll need to add this to the corresponding .js file.

// Set a method on the controller which will send the action
this.controller.set('togglePolicyRead', function() {

If you don’t set this method on the controller, you’ll get a console error like:

Uncaught Error: An action could not be made for `togglePolicyRead` in (generated page.policy-review controller). Please confirm that you are using either a quoted action name (i.e. `(action 'togglePolicyRead')`) or a function available in (generated page.policy-review controller).

As an aside, using Ember’s input component to generate the checkbox will just render into normal HTML (like you see in my first example) and you can confirm that by viewing the page source on your project.

Ember checkbox as HTML with handlebars for the checked property

What if you can’t use the {{input}} component because of a conflict with handlebars syntax? Maybe you’re working inside a component, or there’s some project-specific reason you need to go this route. Here’s an approach you can try that uses HTML for the input and wraps the checked={{property}} in handlebars.

<input type="checkbox"
       {{action "toggleGreen" on="change"}}/>

With this technique, you also don’t have to set up the action on the controller like I showed in the previous technique.

The Ember project I worked on serves its templates as .jsp files and this approach was the popular because we could skip the cumbersome “send” step on the controller. Now, whether that’s “the Ember Way”, I’m too new to Ember to say, but this got the job done.

Blogging for bucks: Year 2 report – growing to greatness

This report is for Year 2 of my “blogging for bucks” endeavor in which I turn my love of research and writing into a profitable hobby. Read about the first year here (it’s a much longer and more detailed post than this one and covers all the “how to get started” stuff).

When I started blogging for affiliate bucks in summer 2013 I said all of the following:

  • “I’m starting too late”
  • “All the good ideas are taken”
  • “The Internet doesn’t need another blogger”
  • “The people who actually make money off this know tricks and secrets I’ll never know”
  • “I’m going to shill products I don’t give a shit about, and it’s going to be boring writing about them.”

Then I went ahead and did it anyway.

Turns out, none of the above was true. 2015 was an excellent year, bringing in more than twice 2014’s haul.


I made $12,600 this year from the Amazon Affiliate program and Google Adsense. Just like in 2014 (my first full year blogging), nearly half of that money was made in the last three months of the year (I love you, holiday shopping season). It wasn’t all for me, though: the IRS took about a quarter of it as their cut in tax season (ow).

2015 Amazon Earnings screenshot
(my earnings are the bottom right number)


I still firmly believe that this is a viable make-money-online strategy that anyone with the willingness to learn, research, and write can do. It’s not too late to start. It’s not even very labor intensive, as evidenced by this “coasting year” still making a decent profit. Most of the work you’ll do is upfront when you set up a new site and load it with your (well-written) content.

To be frank, I ran out of blogging steam for most of 2015. I didn’t write but a handful of articles and I didn’t start any new blogs until December. I was busy with my brand new job and some major life changes.

But if 2014 was the year of sowing, then 2015 was the year of reaping. As the blogs aged, more people found them – and they liked what they found.

2015 Blogging Year in Review


I started my first full-time programming job in January 2015. This was a career change many years in the making and I didn’t have any spare brain cells for my blogs after work each day.

The sites coasted through January – I added no new content and I didn’t promote anything.

But sales didn’t drop with the conclusion of the US holiday season, curiously enough: January 2015 brought in almost as much ($739) as December 1014 ($819). My guess: people go buy themselves the stuff they didn’t find under the tree.

February and March

Sales dropped these months, reaching their lowest point of the year in March ($386). The holiday gravy train had to end somewhere, but I don’t think this was some flaw in my blogs – I think people just don’t buy that much in these months, or they don’t buy that much stuff in the niches my sites are in. Traffic more or less held steady, though, across all sites.

April, May, June, July, August, September

In April sales began to climb again, peaking in August with $1,166! I continued my do-nothing approach and added very little new content during these 6 months (I added 1-2 articles to each of my top-performing niche sites). I put some minimal effort into updating existing content to keep it fresh, though. On Gizmo Blog, this meant keeping up with manufacturer updates to products and industry news.

I think the moral of the story here is to not “give up” on a site. Leave it up, sites are cheap. Even my worst performing sites making $1-2 a month pays for their own domain by the end of the year, and all the while they’re aging like a fine wine (in Google’s eyes).

It’s okay to keep adding content at a snail’s pace, updating here and there, tweaking things along the way. Maybe if you want to make five or six digit earnings every month then you need to add content weekly or daily or whatever, but I definitely didn’t add anything meaningful to my already-established blogs and I was rewarded with a decent “side income” for my complete lack of effort.

October, November, December

Here they are: the three months that make 48% of the year’s income. November was the top-performing month, bringing in $2,076, but December was almost as good, bringing in just $30 less than November.

In honor of the shopping season, I did a few things to help buyers find me:

  • Added a 2015 holiday buyer’s guide and top sellers list for each niche site
  • Tweeted those lists (regularly) from each site’s associated Twitter account

Honestly, I’m amazed that a collection of neglected sites did so well. Imagine what they could’ve done if I’d been adding content all year long!

Year in summary (a pie chart!)

As the chart illustrates, Gizmo Blog accounts for a full 66% of my Amazon Affiliate earnings, and Craft Blog the next 20%. That means a full 86% of my earnings come from just two sites. Better diversifying my Amazon Affiliate income is one of my goals for 2016 – I don’t like having too many eggs in any one blog basket.


“Other” includes this blog, TILCode, which made a grand total of $7 off Amazon Affiliate earnings in 2015 :D (Thank you, whoever bought a book or two through this site.)

What about SEO techniques?!

I chatted with a number of people about blogging for side income in 2015 and the most common question they asked me was, “what kind of SEO do you do?”

The short answer is, I don’t do any.

I pick a product, research it (sometimes I buy it and use it myself), basically obsess over it, and tell people why it’s better than its competitors in a 1500-2500 word review.

I pick products I like myself – stuff I’d buy if I had unlimited funds, or stuff I already own. That’s it! People who want to know this information – people on the cusp of making a purchase – find me through Google and go through my site to Amazon to make their purchase, which I then get a cut of at no extra cost to the shopper.

There are a lot of techniques out there that promises results (paid links, WordPress plugins, content strategies, backlink strategies) and I can’t vouch for any of them. I mean, maybe there’s something out there that would turn my $2,000 months into $5,000 months, but at what cost? Hundreds of dollars in bought backlinks that Google would eventually sniff out and knock me down in the search results for? I’ve been content to build my sites myself and let the natural links come in at their own pace. YMMV.

2016 goals

  • Better diversification – 86% my Amazon Affiliate income comes from just two of my sites, so I want to get that down to 50% by EOY by growing income from other sites.
  • Alternative revenue source – virtually all of my passive online income comes from Amazon Affiliate program. It’s a great program but if it ever goes away, I’ll be pretty sad and won’t have anything to back it up.
  • $18k in earnings – that’d be nice!
  • Set up my blogs as a legal business entity, as per my financial adviser’s advice and because it’ll make tax season easier and more in line with what the IRS expects from a “side business”
  • Optimize sites – load times are bad (>6 seconds in some cases), they’re mostly on shared hosts, I get a lot of “Error Establishing Database Connection” problems (my VPS seems to get overloaded with one site in particular) – there’s just a lot of technical performance things that could be better
  • Actually add more new content to sites

And that’s it for 2015! Onwards to 2016, where I hope to do a better job of adding content and optimizing the sites for even better earnings.

Code School Review: The Magical Marvels of MongoDB gets you started with shell syntax

Code School’s got a new database path! Woohoo!

I was invited by Code School (and comped with a free month subscription) to try out The Magical Marvels of MongoDB. I’m not that experienced with backend data stuff, so I was excited to fill in a bit of my knowledge gap with this intro-level course.


About Code School

As some readers already know, I’m a big fan of Code School is great for both curious newbies (“is coding something I want to do with my life?!”) and for more experienced programmers who want to get a feel for a new technology without going through the hassle of setting up an environment, a new project, and then wading through a pile of documentation.

They’ve grown a lot in just the last year, so check ’em out! Especially if it’s been a while since you last visited.

About the MongoDB course

What you need: a modern web browser – and that’s it. I used Google Chrome and experienced no technical difficulties. All the videos and interactive lessons take place in-browser.

Time spent from start to finish: about 4 hours. The course is divided into 5 sections, with about 10 minutes of video instruction per section.

Topics covered: inserting and finding database documents, transforming record data, filtering documents by various search criteria, embedding vs. referencing, and aggregation.

Overall instruction quality: Excellent. The class’s instructor, Joel Taylor, speaks clearly and concisely. On-screen text is clear and readable, and the graphic design is pleasing and modern.



The course is largely a tour through the syntax used in MongoDB’s shell. The course does a great job of showing the student how MongoDB structures its data and how to perform simple operations like adding, removing, and updating parts of database objects as well as filtering results by more sophisticated criteria.

The error checking is pretty good – it caught most of my bonehead mistakes and the hints were relative to the mistakes made. Occasionally, I ran into a problem where the error checking couldn’t tell me what I had done wrong, such as omitting the “$” before “$lte” in one case, but I never stayed stuck for long.


I liked how the course never gave me ready-made code to work from. I have a vague memory of an earlier Code School course giving me existing code to add to, and I feel like I got a lot more value out of the repetition of typing the same “boilerplate” (ie: db.wands.find() ) each time I started another section.

The pacing was good: I especially enjoyed the multiple-choice format to section 4, which I felt deepened my understanding of embedding vs. referencing and also was a nice change of scenery from the usual coding challenges. Lessons never dragged on too long, so I could squeeze them in between other things I had going on.

I love the in-lesson shortcuts to the relevant video sections, the reviewable slides, and the suggestion near the end of Lesson 2 to look in Mongo’s own documentation for help with $mul. Since I usually work with documentation up on my second monitor, I appreciate the validation. :P


As with many CodeSchool courses, the larger context is probably the thing I miss the most in this course. I loved the intro at the beginning: the conceptual rundown (“NoSQL”, collections, the diagrams), but I didn’t get a great feel for the whys of MongoDB. Why would a project be better served by MongoDB over MySQL? What are the advantages of MongoDB and tradeoffs?

The course is a great way to try out the technology, but for me, finding the syntax of a language or technology is usually the simplest step (thanks to documentation). My personal learning curve tends to steepen as a result of the quirks, the gotchas, and the… mindset (for lack of a better word) of a technology.

And, of course, the usual caveat applies: practicing a language or technology in the browser is a lot like reading foreign language words out of a book vs. attempting a conversation with a native speaker. If you were to actually make a project using MongoDB, you’d find there’s quite a bit of setup, interfacing with the rest of your project, and debugging to get through first. CodeSchool doesn’t cover this aspect of the experience, but it’s a pretty big part of using any new technology.

But hey, these aren’t really problems with the course, just things that an intro-level online class can’t be expected to deliver on in the first place. The fact that I’m missing them is probably a testament to Code School’s ability to get me interested enough in the technology to want to know more.

The bottom line?

Great course! I finished it and wanted more. My favorite parts were the sections that went beyond syntax and into best practices, like the embedding vs. referencing parts. Don’t expect to be able to speak fluently about MongoDB after just this one class, it’s too small in scope for that.

But I’m wishing there was more, so – good work, Code School!


Source Maps – Debug your Bundled, Minified Code

While developing a web app, it’s a good idea to bundle all your various JavaScript files and libraries into a single, minified file for production. Bundling makes your app faster by reducing download size and saving the browser from having to perform multitudes of HTTP requests just to render the page.

However, bundling comes at a cost. Debugging bundled JavaScript is often a nightmare. If your app has an error, the error in the console points at the point in the bundle file where the code failed, which may or may not bear any resemblance to your actual project files.

Which would you rather debug?

Which would you rather debug?

Wouldn’t it be great if the debugger was smart enough to point you at your original, pre-bundled code instead? Enter source maps, a way to preserve reference to your original file and code structure, even through bundling.

Before We Begin

This article uses the following tools, so make sure you have them first (or at least the basic concepts about them):

(PS: Grunt and Browserify can do source maps, too.)

How Source Maps Work

A source map is a composed of data that links pieces of your minified bundle back to the original, unbuilt files. Modern dev tools will automatically follow the map for any console.log or line queries you perform.

Showing The Problem

Let’s say I have a simple console.log in an angularjs controller someplace:

  .controller('CtrlMain', function ($scope) {

When we run the app and look in Chrome’s JavaScript console, it provides a very unhelpful link to where the log was executed:
Screenshot from 2014-11-27 17:07:20Oh, it’s in the one and only line in my bundled script? I never would have guessed.

To generate bundle.js, I’m using the following task in Gulp:

gulp.task('build-js', function () {
  gulp.src([jsDir + 'module.js',jsDir + '*.js'])

This concatenates all JavaScript files into a single file called bundle.js, creates dependency injection annotations so Angular doesn’t choke on the minified code, minifies the code using gulp-uglify, and finally writes it to a build directory.

Adding Source Maps To The Build Process

Here’s how to add source map creation to this build process, using gulp-sourcemaps:

gulp.task('build-js', function () {
  gulp.src([jsDir + 'module.js',jsDir + '*.js'])

Before we do anything to the JavaScript files, we call sourcemaps.init(). This tells gulp-sourcemaps to pay attention and generate our source maps while the build process occurs. sourcemaps.write() signals that we’re done processing the .js files and ready to write out the bundled file.

IMPORTANT NOTE: All plugins used between sourcemaps.init() and sourcemaps.write() must be supported specifically by gulp-sourcemaps. You can find a list of supported plugins here.

The Final Product

Now let’s build and run the app again and see what we get:

Screenshot from 2014-11-27 18:19:39

Much better

Now the console.log behaves as if we’re working with the clear, unbuilt versions of our files. We can click that link on the left to see exactly which line contains the log. Ahhhh.


7 IntelliJ IDEA tips and settings you’ll probably love

Hardly a week goes by where I don’t learn something new about IntelliJ! Here are just a few of my favorite IntelliJ settings tweaks and workflow tips.

This article was written for IntelliJ IDEA 14 professional and community editions.

1. Exclude some folders from search

If searching in your project is returning a lot of non-project files you’d rather not see (such as files in /node_modules, /tmp, or /build), you can permanently exclude those files.

Go to File > Project Structure > Project Settings > Modules. Right click any folders you don’t want to ever search in and mark them as Excluded. Done!


2. Highlight current file in project hierarchy

Do you want to see where your currently active file is in the project structure? Of course you do. Turn on “Autoscroll from Source” by clicking the little gear in the little toolbar at the top of the project structure window.

Now whatever file you’re editing will be automatically highlighted in the project structure pane.


3. Start a local server with a single click

For all your little web projects that you want to test in browser without bothering to set up a server first, just right click the file you want to serve and choose Open in Browser.


I overlooked this feature in the past because I thought it was just going to open the file all vanilla and stuff, but it totally starts a little standalone server! 


4. Resolve git conflicts

IntelliJ IDEA’s git merge conflict resolution tool is fun and convenient. Just right click in any of your project’s files (doesn’t have to be the one with the conflict in it) and go to Git > Resolve Conflicts…


You’ll get a modal with a list of all the files containing conflicts. Choose Merge…


In this screen, you can compare your changes (on the left) to what you got from the server when you pulled (on the right) and view the result (in the middle). Move changes to the result by clicking on the >> and << symbols, and reject changes by clicking the X. You can even edit the final version manually right there in the middle pane.



You know you’ve seen it… somewhere. But your project is huge and that file could be anywhere. Double-tap the Shift key to open up Search everywhere. I use this shortcut to hop between files all the time because it’s just so convenient.

6. GitHub integration

In the right click menu (click inside a file or on a file in the project hierarchy) there are a couple shortcuts to GitHub. Open on GitHub is handy for jumping right to the file you’re working on to view its history, Create Gist is handy if you like making Gists.


7. Turn on Annotations to know who to blame (it was probably you)

Who wrote this line of code? Now you can know: right click in the left margin (where the line numbers are) and turn on Annotate.


Hovering your cursor over individual lines reveals the last commit message, too.


There you have it: a short ‘n sweet guide to 7 helpful IntelliJ tools, shortcuts, and settings.

pytest CLI tips, tricks, and additional settings

There are several Python unit testing frameworks, but pytest is both the most popular and the easiest to use. It requires no boilerplate, no imports, no API. Just name your files, classes, or methods starting with “test”, type py.test into the command line, and observe the results.

Simple, right? And we want it that way. Pytest allows our tests to be uncluttered and easy to read. But as far as the output of those tests goes… we can do better! This article will show you how to master the pytest CLI.

To start off, make sure you have pytest installed:

pip install pytest

For those of you new to pytest, note that the package is named “pytest”, while the command to run it is “py.test”. The dot remains for historical reasons: pytest used to be part of the “py” library.

If you already have pytest installed, double-check your version number:

py.test --version

This guide is written with pytest version 2.7.0 or greater in mind. If you have an older version, you can upgrade using pip:

pip install --upgrade pytest

All good? Let’s get started!

Useful Switches

-x : Stop After First Failure

When you’re trying to track down a bug, it can help to run all of your tests, so that you can draw conclusions based on what groups of tests are failing.

That said, sometimes you just want to work through failing tests one by one, or there are so many tests in your project that running them all every single time (not to mention sifting through all the output) would be too time-consuming. There’s a nice simple switch to take care of this:

py.test -x

This will stop pytest after the first failure is encountered, saving you oodles of time. Is one just not enough? How about after two failures? No problem!

py.test --maxfail=2

-k : Run Tests Matching Keywords

What if you know some group of tests is going to fail, but you just don’t want to think about them right now? You could go through your test files and comment them out… but there’s a much better way! Let’s say you only want to run tests with the word “log” in the names:

py.test -k “log”

Easy… but wait! This also ran the tests with “logout” in the names. Let’s say we don’t want those:

py.test -k “log and not logout”

That’s right! Instead of just a simple string match, you can feed -k a full expression to use.

Controlling Verbosity

Of course, if you want to run all your tests, but just make them run more quietly, you can tone down their output like this:

py.test -q

The opposite is increasing the output, which will put all the names of your tests in a list, along with their pass and fail states:

py.test -v

This can be useful if you’re logging your tests for someone else to read. This will only control the state output, however. For the rest, see the next section!

Changing Defaults

Changing Traceback Printing

When a test fails, pytest will attempt to do a traceback to give you some information on what went wrong. And when I say “some”, I mean a lot… often too much. What if you could shorten that output, so that you didn’t have to scroll for pages to see the results of all your tests? Well, try this:

py.test --tb=short

Using –tb will change pytest’s traceback formatting to the format you specify. If “short” is still not short enough, you can do it one better:

py.test --tb=line

Or if you’re looking for something a little more familiar, you can set pytest to use the Python standard traceback formatting, like so:

py.test --tb=native

Invoke pdb On Failure

Oftentimes, when debugging a problem, you’ll stick the following statement on the line before the test failed to set a pdb breakpoint:

# code here
import pdb; pdb.set_trace()
# more code here

But why go through that hassle, when you can just do this when you run pytest?

py.test -x --pdb

This will invoke pdb immediately upon failing a test. Notice that I combined it with -x to stop pytest after the first failure. This combination is quite useful, as you don’t want to have to go through pdb for every single failing test.

Watching Files

All of these tricks will help you save time and energy while running tests. But all of them have one thing in common: you still have to head back into the command line and type them out. Well, we can take care of that, too. Enter pytest-xdist. This handy little package (in addition to other things) can keep an eye on your project files and re-run your tests every time it detects something has changed. Just install and run with the -f option:

pip install pytest-xdist
py.test -f

This will immediately run all of your tests, then sit and wait for any file to be changed. Even better, if any tests failed in the previous run, it will re-run ONLY those tests until they pass.

Alternatively, you can use a package called pytest-watch:

pip install pytest-watch

The downside to pytest-watch is that it’s a separate executable, and therefore you can’t use any of the tips in the rest of this article. On the other hand, it has some neat options, like configuring actions to occur on test failure. If you’re on OSX, try this out to have your computer actually vocalize how your tests are doing:

ptw --onpass=”say passed” --onfail=”say failed”

Final Thoughts

These are some of my favorite pytest options, but it’s really only the beginning. pytest has many options for reporting, collection, and debugging, and that’s not even getting into the rich assortment of plugins and packages to extend its capabilities. You’re going to be spending a lot of time running tests, so take the time to poke around and find the configuration that works best for you. It’ll be worth the investment!

How to quit Vi (and more tips for getting started with Vi)

If you opened vi or Vim because you heard it’s what all the cool kids use, chances are your first question is “Aaaaah! How the heck do I get out of this bizarre thing?!”

Don’t panic! Press the Escape key, to make sure you’re in Command Mode. Type “:q“, without the quotation marks, and press Enter.

If you get an error message saying “No write since last change”, type “:q!” and press Enter. You should now be back in your normal command line interface.

Phew! That’s a relief, huh? Now that you’re safely out of vi, here are some reasons why you should go back in and learn how to use it.

Reasons to use Vi (or Vim)

Vi (and usually Vim) is on practically every Unix-like system in existence

Vimlogo.svgVi is specified in the POSIX standard, which means that practically any flavor of Unix or Linux will include it. Sitting down at a coworker’s computer? Vi is waiting for you. Using SSH to go into a completely foreign system with literally nothing but the OS installed? Oh, hi vi, nice to see you again!

A brief note on the difference between vi and Vim: vi was written back in 1976. Vim is a “sequel” of sorts to vi that added features like syntax highlighting, scripting, advanced regular expressions, a help system, and more. I’m using Vim, but my understanding is the basic command structure is shared by both programs.

It’s fast to use

Or it will be, once you’ve used it enough. You rarely have to take your hands off the keyboard to complete almost any text editing task you can think of. In addition, vi’s interface is optimized such that the most commonplace tasks are on the home row, and extremely quick to perform. An experienced vi user can be extraordinarily productive.

It’s what all the cool kids use

Don’t underestimate the benefits of peer pressure! Vi and Vim have a huge community of users who swear by them, some of whom have been using it for decades. Through countless iterations of hardware and software, vi has stood the test of time as the preferred text editor of programmers and sysadmins everywhere. That’s got to count for something, right?

I could go into how powerful and customizable the vi editor is, but I’m just starting my own exploration of it, and frankly, the most important thing is that you can perform basic tasks, so the editor stops feeling like an alien torture device. Deeper understanding can wait until you’re comfortable. So let’s move onto:

Vi / Vim Basics

Opening vi

To open vi, open a terminal window, type “vi“, and press Enter. To open a file with vi, type the filename afterwards, as in “vi filename.txt“. If that file does not exist in the local directory, vi will begin creating a new file with that name.

Type “i” to enter Insert Mode

Vi is a modal editor, which means that the commands you can use depend on which mode you are in. When you open vi, it defaults to the Command Mode. For people who are used to standard text editors, Insert Mode will be far more familiar. Press the “i” key to enter Insert Mode, then begin typing normally. You’ll see your text entered onto the screen.

Undo and Redo (Vim only)

When you’re starting out, it’s natural to make mistakes. To undo, first make sure you’re in Command Mode (by pressing the Escape key). Then tap the “u” key. You should see your last change undone. You can keep pressing “u” to back up through vi’s change history. To redo, press “Ctrl + r” (“r” by itself is the Replace command).


h“, “j“, “k“, and “l” in Command Mode correspond to left, down, up, and right respectively. This will seem really weird at first, but using the keys right in the home row makes it very fast to navigate.

Note that you can use the regular arrow keys as well, but you should try your best to get used to the home row keys. Train that muscle memory: it’s worth it.

For faster navigation, use “Ctrl + u” and “Ctrl + d” to half-page up and down, respectively. There are many other ways to navigate a file as well, but these will serve you well enough for now.

Saving and Quitting

Once you’ve made some changes, type “:“. You’ll now notice your cursor is at the bottom of the terminal window. Press the “w” key so that the bottom of the window says “:w“. Press Enter, and you’ll get a message that your file was saved.

As mentioned above, you can now type “:q” to quit vi. If you tried to quit without saving, you’ll get an error. You can type “:wq” to save and quit at the same time, or “:q!” to quit without saving.


Type “/” in Command Mode to open a search prompt at the bottom of the window. Then type whatever word you want to search for and press Enter. To go to the next search result, press the “n” key. To go to the previous result, press “Shift + N“.

Basic Vi Cheat Sheet

Quit without saving


Save and quit


Enter insert mode


Move left / down / up / right

h  j  k  l

Beginning of word / end of word

b  e

Move to the end of the line


Page up / page down

ctrl + u   ctrl + d

Leave insert mode


Search (must be in Command Mode)


Next Steps

You now know enough about vi to use it for simple tasks. Once you’re comfortable with the above, try typing “vimtutor” at the command line for a nice tour of some of Vim’s intermediate features.

Vi and Vim have a vast array of commands and customizable elements, far more than any blog post can hope to cover. Once I’m a little more familiar with Vim myself, I’ll post a follow-up article with some good tips.

In the meantime, here are some helpful resources on Vi:

Code Fellows Post-Accelerator Update (4 months into first job)

It’s been…

  • Several years since I first dreamed of writing script or code for a living
  • 1 year since I left my unhappy video game designer job
  • 6 months since I graduated from the Code Fellows Full Stack JavaScript Dev Accelerator
  • 4 months since I started my full-time programmer job

What a trip! Thanks to Code Fellows in Seattle, I am super happy to report that I am now a full-time programmer and loving my new job!


I had tinkered with coding for years in my free time, but never in a substantial enough capacity to turn it into a full time job on my own. Code Fellows was that missing piece, and this is my post-Accelerator update!

My review of the Seattle-based Dev Accelerator can be found here, if you’re curious about the 8 week program itself.

Yes, I got a job after Code Fellows!

@CodeFellowsOrg is now in Chicago and Portland!

And it’s a great job! Like, an unbelievably great job where they pay me to solve interesting Angular and JavaScript problems! My title is Associate Software Development Engineer and I work at Expedia in Bellevue, WA.

So, yes, to all those wondering (and emailing me!), Code Fellows will work you hard, but it is sufficient training for an entry-level programming job (provided you do your part), and the skills you learn in the class will be useful in your job, even if your job is in a different language or technology stack.

Job search rocket fuel: The mid-accelerator resume blast

Code Fellows definitely made good on their promise to put student resumes in front of local employers. Halfway through the Accelerator (4 weeks in), Code Fellows collected and reviewed resumes from every student and fired them off to 40+ Seattle and Eastside employers. Holy wow – they knew about companies I’d have never found on my own.

The “blanket the city” approach worked, but I had a few small gripes that I think other students should be aware of.

  1. The resume blast went to companies I wasn’t interested in (…yet). I gave preference to companies closer to me on the Eastside (so I wouldn’t have to relocate), but my resume went to plenty of companies in downtown Seattle. I felt bad turning down these companies (burning bridges! ahh!), especially since I knew I would become more interested in relocation if my job search started to drag on.
  2. I prefer to customize my resume and cover letter to each position, emphasizing different aspects of my experiences for different positions.
  3. The blast went out too early. My final Accelerator project, my post-Accelerator project, and my portfolio website were not on that early version of my resume. Employers I talked to over the next couple months didn’t know about these things, and those projects and my portfolio site were the strongest showcases of my work.

Basically, I didn’t have iron-clad control over my job search in the first few weeks. And I like iron-clad control over my job searches.

I had only a vague sense of which companies I had already “applied” to and I inadvertently wasted the time of employers I probably wouldn’t have applied to on my own (because they were too far away or didn’t have the kind of workplace culture or benefits I was looking for).

But if that’s my biggest gripe, then I don’t have much to complain about. Code Fellows did a good job supporting its grads, and a quick glance at my fellow classmates’ LinkedIn profiles suggests more than half have already found full time gigs.

Really, I didn’t have to look hard for interesting job opportunities after graduating, and I still don’t – Code Fellows continues to send job leads to alumni, and my LinkedIn profile gets so much email I’m kind of afraid to look in that inbox.

The First Calls

The first couple weeks after my September 26th graduation were really quiet (which was good, I don’t think too many people want to go straight from the Accelerator to a full time job) and then I started getting calls and emails from employers in late October and early November.

Most of these came from “resume blast” employers, but I also ended up in the hands of some recruiters trying to fill really short project positions (like, 3-week or 2-month contract projects). I thought these projects sounded exciting but all of these opportunities fell through for some reason or another.

A big question near the end of the Accelerator that many students asked was whether recruiters were worthwhile. I’ve personally never had a productive relationship with a recruiter in nearly ten years in tech, but someone must be getting value out of recruiters since they’re still in business.

For whatever it’s worth, the three companies I ultimately interviewed with contacted me directly, either via their technical director or their own hiring department, with no recruitment firm involved.

Technical Interviews

By mid November I had phone interviews scheduled with three companies. Two of them had my info from Code Fellows, and one of them I had applied to on my own. Of those three companies I interviewed with, two chose to conduct the technical interview over the phone.

The first company had a setup where I shared a screen with my interviewer and coded in real-time as my interviewer watched and talked to me over the phone.

The second company conducted the technical interview as a series of questions, sans-computer, although my interviewer had poked through my Github repos and had some questions for me about code I had posted to Github.

The third company (where I now work!) brought me in for a one-hour in-person technical interview, which I really enjoyed and preferred over the phone interviews. This technical interview had the most in common with Code Fellows’s style of interview training, where the interviewer asked me questions and I wrote code on the whiteboard and answered questions as we went along.

In all three technical interviews with three different companies, I felt that my Code Fellows training and in-class interview practice had sufficiently prepared me for the questions I was asked. I was asked questions I didn’t know the answer to in all three interviews, but it wasn’t the end of the world. I just said I didn’t know, said what I would do to find out, then said that I would love to know, and in all cases, my interviewer explained whatever it was to me. (Yay, I learned something new!)

Technical Interviews: Questions I was asked

In no particular order, here are the kinds of questions I remember being asked:

  • Write a function that determines if a string is a palindrome
  • What does REST mean? Why is it important?
  • Write a function that returns just the odd numbers from an array I pass into it
  • Now modify that function to return every other odd number
  • Describe dependency injection in Angular
  • Tell me what kinds of tests you would write for that (whatever that was)

Keeping up after the Accelerator

I filled my post-Accelerator free time building a brand new AngularJS app of my own, a sort of “capstone project” that summarized my knowledge thus far. This project kept my skills fresh and I would recommend other Code Fellows grads do the same (after graduation, of course) to really solidify their understanding of the concepts likely to come up in interviews.

My post grad project: a recipe site with a back-end interface for adding and editing recipes. I rolled my own CSS and it even has automated tests!

I brought this project with me to my interview on a laptop so I could show it to my interviewer, and that seemed to go over very well. (I got the job, after all!)

Other things I did to stay sharp after the Accelerator:

  • Codewars “kata” – some of these were really hard but they’re also one of the only training things I’ve found that includes testing
  • Updated my WordPress blogs’ themes and added customization I always wanted but never really understood how to do before (this stuff was easy after the Accelerator)
  • Built my coding resume / portfolio site from scratch
  • Aimed for a minimum of 1 meaningful Github push per day on whatever project of my choosing (I find streaks and those little green cubes very motivational)
  • Read up on concepts I learned about in the Accelerator but wanted to understand better, like Big O, asynchronous Javascript, data structures

My first month on the job

Like many grads, my primary fear going into my first programming job was that I wasn’t sufficiently qualified. I still felt pretty green, despite all my experience. (Some people tell me this feeling of being inept despite accomplishments that prove otherwise may never fully go away, and recognizing that definitely helped.)

My first week on the job was spent learning the code base, the project structure, learning the workflow (how to run tests, how to get a build running), and setting up my work laptop.

There was so much to learn, and this project is so much more complex than anything I’d coded in before. (This is why I think building real, standalone apps / programs is best for learning to code once you’re past the online tutorial basics.)

My work project is more complex than anything I ever built on my own.

Fortunately, everyone was happy to help and answer questions, and I quickly found several more Code Fellows alumni at the company who started before me or on the same day as me. We met up at a local Starbucks early on to share experiences, which was reassuring for everyone involved.

In that first month, my main contribution was adding a button that exposed a back-end feature the rest of the team had been working on for some time. I wrote the logic that determined when that button would be clickable, and added unit and end to end tests to help spot any future regressions.

I also had the opportunity to debug existing Ruby/Cucumber tests, learn a little bit of Scala, and write a few MySQL queries to look at how data was saved in the database. In that first month, I found that the biggest challenge wasn’t writing new code, it was understanding existing code and the complexities of the project’s structure.

The next 3 months

Around weeks 5-6 I started to feel like a more full-fledged, contributing member of the team. The vast majority of my work is in modifying existing code to perform a new function or to fix an unwanted behavior.

Here are just a few of the things I worked on in that time:

  • Small optimizations to Cucumber test suite aimed at reducing the test code’s reliance on fragile XPaths and removing sleep() and wait() calls
  • Improvements to the way dates are handled in the app, including adding the much-beloved moment.js library to the project
  • Collaborating with another programmer to develop a date range “collision” algorithm that can check if a variety of date ranges overlap correctly (or incorrectly) according to a complex set of business rules
  • Upgrade project’s Angular version and assist in the migration
  • I had the opportunity to attend a day-long Test Driven Development workshop and bring those practices back to my daily work

My team’s leaders are big fans of pair programming (to the extent that we have dedicated 1pm-4pm “core pairing hours” every day), so a lot of the work I do is in the company of at least one other engineer. I’ve learned so many good techniques and habits from working with my teammates, and I can’t overstate how great this has been for my own development and quick integration with the team.

(I hope it’s apparent from my writing here how very happy I am to be working on this project with this team – I love it, it’s better than I ever dared to hope.)

Happy Ending / New Beginning

So that’s it! I can’t believe it’s been six months already. The Code Fellows Accelerator changed my life: my new role is challenging, and working at Expedia with my team has kept me just as inspired and excited as I was when I embarked on this journey a year ago.


Using tags to run select Cucumber tests

Today I learned… that I can “tag” select Cucumber scenarios and run just the tagged ones, speeding up my testing and making it faster to debug a failing test.

I’m working with Ruby Cucumber tests for my current project and as the tests grew in number and complexity, I found myself wanting a way to run just a specific test.

If your tests are set up anything like mine, you can just add a tag with an @ symbol to your tests like so:

@javascript @tagname
Scenario: Verify that the thing in the thing works
Given I am already logged in
And the page has finished loading
Then the thing should be in the thing

When you run your Cucumber tests from the command line, just add –tag @tagname as an argument:

cucumber --tag @tagname test/specs/features/testfile.feature

This is just a simple implementation that might be useful if you are trying to debug a single test. Taken to its logical conclusion, you could have entire suites organized under different tags for different purposes, environments, etc.

More Reading

Most of what I know about Cucumber tagging came from’s excellent guide on Cucumber tagging.