Feb 24

Achievement Unlocked

[This post is adapted from a lightning talk I gave at the Testing in Python Birds-of-a-Feather session at PyCon 2010.]

One of those most fun advancements in video games in recent years is not about the improved graphics, or playing with hundreds of people at once. It’s that games have evolved beyond points. While a good point system may be a good indicator of a player’s abilities, it doesn’t tell the whole story. Many modern games, even if they don’t involve points, have introduced the concept of achievements. Achievements are awarded for completing game-specific challenges—essentially, they are merit badges.

Examples

From Team Fortress 2:

From The Beatles: Rock Band:

From foursquare:

These add another level of fun to the games in question. I think it’s about time we stole this idea for software testing.

Testing Achievements

To make this happen, I announced an Achievements plugin for nose, the Python test runner. Here are a few highlights:

Night Shift
Make a failing test suite pass between midnight and 5am.

Punctuality
Make a failing test suite pass at 9am.

Coffee Break
The test suite takes between 5 and 15 minutes to run.

Happy Ending
All tests in the suite fail…except the last.

My God, It’s Full of Dots
The suite has at least 2,001 passing tests.

Sausage Fingers
At least two distinct syntax errors are raised by the test suite.

Are You Mocking Me?
Import a mocking library.

100% Code Coverage, Level x
100% of at least 2(x+7) statements are executed.

You can view the full list of achievements here. Many of these are working right now.

Next Steps

Announcing unlocked achievements on Twitter or IRC, global or project-specific leaderboards, pluggable achievement expansion packs…

Share your ideas in the comments!

Jan 22
Phaeton by Kevin Cornell & Randy Jones. This typeface really stood out in ILT’s favorites of 2009. Love it!

Phaeton by Kevin Cornell & Randy Jones. This typeface really stood out in ILT’s favorites of 2009. Love it!

Nov 11

Emergency party at my place

Dear Reader,

You knew keeping this blog in your RSS reader would pay off one day, didn’t you? You did, right?

Well now you can reap the rewards, my friend. There comes a time.

You are invited over to my house on Friday, November 13 for a party and performances by several talented musicians.

There will be a full bar. Also an actual, physical bar. Celebrated Clevelander Marta “Martender” Lapczynski will be bartending.

We’re getting started at 10 PM; music at 11. Everything is free.

Here’s your invitation with the details:

See you there, Internet lovelies!

Apr 17

“The Cleveland Tourism Board gave me 14 million dollars about 8 months ago to make a promotional video to bring people to Cleveland. As usual, I waited till the last minute and I ended up having to shoot and edit it in about an hour yesterday afternoon.” — bishopvids

Feb 19

Cleveland Code Co-op meeting on Sunday

The fifth meeting of the Cleveland Code Co-op will commence this Sunday, February 22, from 13:00 till 19:00. We’re expecting more participants than usual, and likely projects so far include:

  • redit, a text editor in Ruby
  • 80sheep, an ADC (peer-to-peer) client in Python
  • a Python tutorial for beginners
  • your wildest software fantasies

This month’s meeting will take place in the EECS student lounge at Case Western Reserve University, which is located in the Glennan Building. Directions are located on the wiki. You can also join us on IRC in #C3 on irc.freenode.net.

Food and drinks will be provided! Hope to see you there.

Jan 29

Python instance descriptors: when class descriptors aren’t dynamic enough

Python descriptors are great for customizing access to attributes on a class or instance. They are a big win for tasks like mapping Python objects to data from non-Python sources (such as SQL), since mapped attributes will need to be encoded/decoded and connected to other attributes in some way.

Below is a very simple descriptor; as you can see, accessing it from both the class and the instance invoke the descriptor protocol:

class Test(object):
    pass

class Descriptor(object):
    def __get__(self, instance, owner):
        return "Hello, world."

>>> Test.x = Descriptor()
>>> Test.x
'Hello, world.'
>>> test = Test()
>>> test.x
'Hello, world.'

However, in order to add descriptors to an object, they must be added to the object’s class. Descriptors added to an instance do not invoke the descriptor protocol:

>>> test.y = Descriptor()
>>> test.y
<__main__.Descriptor object at 0x16fe810>

This means that creating an instance with dynamic (determined at runtime) descriptors requires either the heavy-handed approach of generating a class just for that object (since adding descriptors to its class will add them to all other instances of the class), or the ad-hoc approach of redefining getattr/setattr behavior (essentially re-implementing your own descriptor protocol).

It turns out the latter approach is not as messy as it first sounds. Below is a class that enables “instance descriptors”:

class InstanceDescriptorMixin(object):
    def __getattribute__(self, name):
        value = object.__getattribute__(self, name)
        if hasattr(value, '__get__'):
            value = value.__get__(self, self.__class__)
        return value

    def __setattr__(self, name, value):
        try:
            obj = object.__getattribute__(self, name)
        except AttributeError:
            pass
        else:
            if hasattr(obj, '__set__'):
                return obj.__set__(self, value)
        return object.__setattr__(self, name, value)

class Test(InstanceDescriptorMixin):
    pass

>>> test = Test()
>>> test.z = Descriptor()
>>> test.z
'Hello, world.'
Jan 6
“The purpose of syntax highlighting is to turn your code into a map, not The Jimi Hendrix Experience.”
Dec 13

geopy sprint at December C³ meeting

Today (Sunday) the third meeting of the Cleveland Code Co-op will be held from 1pm to 7pm at Gypsy Beans & Bakery. We’ll be focusing on geopy again, continuing our sprint goals from last time. All are welcome to attend. You can join us via IRC in #c3 on irc.freenode.net.

Christmas tree adventure

I’ve never taken the time to get a Christmas tree while living on my own before because, honestly, Christmas doesn’t mean much to me. But having moved into a spacious single-family carriage house with Steve, it sounded a lot more fun to drag a big needly tree into my living room this year. Today Mandy and I drove all the way out to Tower-N-Pines Farm to cut down our own tree. We followed this up with dinner at Mary Yoder’s Amish Kitchen, where Mandy told me everything she knows about the Amish (Middlefield has the world’s fourth largest Amish population).

I was hoping for an axe, but they only provided hacksaws. I then realized that, despite being cooler and more fun, an axe would have required blindly swinging your arms into the branches: Brian holding a hacksaw

We did a lot of walking and probably looked at every single tree. This took a long time: Brian walking among the trees

We settled on this one: Brian crawling under the tree

Finally, the moment I had been waiting for: Brian cheerily cutting the tree

Mandy even got her chance to make this face: Mandy making a fierce face with hacksaw

It worked: Brian felling the tree

Note all the inferior trees in the background: Mandy holding the felled tree

Then there was dragging: Brian dragging the tree

We tied it to the roof of Mandy’s car using the rope from my grappling hook (farm’s ropes? $11). It arrived safely: Brian preparing the tree

Steve made up for his non-participation by helping “unfell” the tree: Steve holding the tree at home

Real mature, Steve: Steve pretending to hit Brian with a hammer

Steve guesstimates that the tree is “almost 10 feet” tall. Steve and Brian admiring their tree

Dec 2
Roomba decided to take its docking station &#8212; originally placed in a much more sensible location &#8212; for a walk.

Roomba decided to take its docking station — originally placed in a much more sensible location — for a walk.

Page 1 of 6