Black-box testing is a method of software testing that examines the
functionality of an application (e.g. what the software does) without peering
into its internal structures or workings (Wikipedia). While it’s
usually done at a system level, I think the most obvious place it should be
used is at the function level. It’s even more efficient if you write tests for
someone else’s code.
Here is how I write unit tests for functions.
Good Names
If you can’t tell what the function roughly does only by looking at its name,
it’s usually because it’s badly named or it’s doing too many things, maybe you
should break it in smaller functions. Look at its arguments names. Do they make
sense to you? Do you understand what’s the function doing only by looking as
its name and its arguments?
Good Documentation
You sometimes need to read a function’s documentation if its name is unclear or
if it’s a complicated code area. This is your latest chance to understand the
function, because in function-level black-box testing you can’t read the code,
it would not be black-box anymore. If you understand the function, you can now
write tests. If not, you should improve its name, its arguments names, and its
documentation, in that order because it’s the order one reads it.
Good Tests
Good unit tests are short, incremental, and test only a specific case. Start
with the simplest. Does the function takes a string? Give it an empty one. Does
it take a number? Give it 0. Use null for objects. Then move to more edge
cases: negative numbers, un-trimmed strings, uninitialized objects. Add more
simple edge cases, but only once at a time. Then, combine those edge cases.
Write more complex cases. Never combine two cases you never individually tested
before. After all these edge cases, test the legitimate ones. Again start with
the simplest, then add more complexity and combine cases.
I discovered a great feature in Vim today. While we generally
use the same Vim settings everywhere, we sometimes (have to) contribute to
projects with a coding style different of ours, and because nobody wants to
edit their .vimrc everytime to switch between configurations, Vim allows you
to have per project .vimrc’s.
This feature can be enabled with one line in your .vimrc:
When you start Vim, it begins by looking at some predefined locations for a
configuration file (the first one is $HOME/.vimrc). The exrc option,
disabled by default, tell to Vim to not only load your personal .vimrc, but
also to look in the current directory to check if there’s another .vimrc file,
which will be loaded after your personal one. You can then use it to override
your settings and/or add specific ones for this directory.
Additionally, if you share the local .vimrc with others (e.g. in a Git
repository), you may want to set the secure option at the end of your personal
.vimrc:
This disallow shell and write commands in the .vimrc of the local directory.
On unix-like OSes, this option is set by default if
you’re not the owner of the file.
In this post, we’ll create a custom TLD for local development, and configure
Apache to work with that. It’ll allow you to work on your local version of
mysuperwebsite.com with the local domain mysuperwebsite.dev, with the exact
same URLs, except that little .com which is replaced by .dev.
This post is focused on OS X, but the tools used are available on Ubuntu and
others. Additionally, you can choose whatever unexisting domain you want, just
replace .dev with the one you chose in the commands described in the article.
DNSMasq
The major problem we have when we develop locally with custom domains is that
we have to add an entry to /etc/hosts for each website. Wildcards are not
supported, so you can’t write the following line in it:
127.0.0.1 *.dev
There are different workarounds, but here we’ll use DNSMasq as
a local DNS resolver. If you don’t have homebrew, install it
first, then install DNSMasq:
brew install dnsmasq
# enable the daemon on startup
sudo cp $(brew --prefix dnsmasq)/homebrew.mxcl.dnsmasq.plist /Library/LaunchDaemons/
DNSMasq will run locally and redirect any query for a *.dev domain to the local
host, 127.0.0.1. Open /usr/local/etc/dnsmasq.conf (or create it if it doesn’t
exist) and add the following lines:
address=/dev/127.0.0.1
listen-adress=127.0.0.1
Then start DNSMasq:
sudo launchctl load homebrew.mxcl.dnsmasq
You’ll have to tell OS X to send its
DNS queries to the local server first, then try the other ones, to intercept
the queries for the *.dev domains. Go to System Preferences → Network →
Advanced → DNS, and add 127.0.0.1 at the top of the list of DNS servers.
You can then check that it works using dig:
$ dig foobar.dev
…
;; QUESTION SECTION:
;foobar.dev. IN A
;; ANSWER SECTION:
foobar.dev. 0 IN A 127.0.0.1
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
…
If you have some
server listening on port 80, you can try foobar.dev in your browser, it’ll
display whatever you’re serving on 127.0.0.1:80. If you have any troubles,
empty your cache (use dscacheutils -flushcache on OS X), or restart your
computer.
That’s all! You can stop there, but if you’re using Apache you may be
interested by the next section of this article.
mod_vhost_alias
This Apache module allows you manage virtual hosts dynamically, so you won’t
have to create a new one for every (local) website. This is useful if you have
a large number of virtual hosts with similar configurations. In this section,
we’ll see how to associate a .dev domain with a directory on your computer.
We’ll assume you already have Apache installed and working.
With mod_vhost_alias, Apache extracts the hostname from the client query (with
the Host HTTP parameter) and use it to get the directory path. The official doc
has a lot of examples, I personally prefer to be able to use whatever directory
name I want, so I’m using a vhosts directory which contains symbolic links to
the right directories. Like with DNSMasq before, you need to add only two lines
of configuration here. Open /etc/apache2/extra/httpd-vhosts.conf (you’ll need
to use sudo), and add the following lines at the end of it:
You may want to customize the path. This one takes the last two parts of the
domain (i.e. the domain and the tld), and use the directory
~/some/dirs/vhosts/domain.tld/ for it. Note that it’ll use the same directory
for bar.dev, foo.bar.dev, qux.foo.bar.dev, etc.
Then, use ln -s to make symbolic links from vhosts/ to the right directories,
e.g.:
If all the websites are in the same directory, you can skip the
“symbolic links” part. Restart Apache with sudo apachectl restart (on Ubuntu,
use sudo service apache2 restart), and you’re done. In the future, you won’t
have to restart Apache for each new site, you need to restart it only when you
modify its configuration.
If you get some issues with rewrite rules, add
in the .htaccess of the websites that use them, and it’ll work.