www.BrettDaniel.com

JUnit Theories

This semester I am overseeing two undergraduate senior theses. The two students are working on a project involving JUnit Theories. Theories are a very useful feature of JUnit, but they have not been widely adopted since they are still experimental and not documented very extensively. The project's short-term goal is to address this problem by writing a suite of Theories for use as benchmarks in testing research. In the longer term, we hope to apply knowledge gained by writing Theories to other research projects and find areas in which Theories can be improved.

This post describes what Theories are and what they do. In future posts, I hope to write about why I find them interesting and how they enable more complex testing tasks.

"Theories in practice: Easy-to-write specifications that catch bugs" defines Theories in the following way1:

[Theories] are partial specifications of program behavior. Theories are written much like like test methods, but are universally quantified: all of the theory’s assertions must hold for all arguments that satisfy the assumptions...A theory can be viewed in several ways. It is a universally quantified ("for-all") assertion, as contrasted to an assertion about a specific datum. It is a generalization of a set of example-based tests. It is a (possibly partial) specification of the method under test.

To understand what this definition means, it is easiest to explain a simple example. Say we have a simple Counter class that allows one to increment an integer value every time the increment method is called.

public class Counter {
    private int value;

    public Counter(int init) {
        this.value = init;
    }

    public void increment() {
        value = value + 1;
    }
		
    public int getValue() {
        return value;
    }
}

We wish to test that incrementing always increases a counter's value by one. The standard way to test this functionality is to write an example-based unit test that creates a Counter, increments it a few times, and asserts that the incremented values are correct.

@Test 
public void testIncrement()	{
    Counter c = new Counter(3);
    c.increment();
    assertEquals(4, c.getValue());
    c.increment();
    assertEquals(5, c.getValue());
}

This is a useful test, but it only verifies that a single counter initialized to three is incremented correctly. It would be good to test additional counters initialized to many different values. Doing so using example-based testing requires multiple test methods or testing objects in a loop.

Theories provide an elegant alternative that complements example-based tests. From the test writer's point of view, Theories are just like normal unit tests but with one or more parameters.2 To test incremement, one can write a Theory that accepts a Counter object, increments it, then asserts that the value has increased by one. This is more general than an example-based test because it verifies a property common to all counters, regardless of how they were initialized. In the following code, the incrementTheory method implements such a Theory.

@RunWith(Theories.class)
public class CounterTheories {
   
    @DataPoints 
    public static Counter[] data() {
        return new Counter[] {
            new Counter(0),
            new Counter(1),
            new Counter(-1),
            new Counter(Integer.MIN_VALUE),
            new Counter(Integer.MAX_VALUE), // overflows when incremented
        };
    }

    @Theory
    public void incrementTheory(Counter toIncrement) {
        int oldValue = toIncrement.getValue();
        assumeTrue(Integer.MAX_VALUE != oldValue);
        toIncrement.increment();
        int newValue = toIncrement.getValue();
        assertEquals(oldValue + 1, newValue);
    }

    //... more theories 
}

The @RunWith(Theories.class) annotation tells JUnit that it should run all methods in the class that are annotated with @Theory. The @DataPoints annotation marks methods that return values that JUnit should supply to applicable Theories. At runtime, JUnit matches the values returned from data point methods or fields to appropriate Theory parameters.3 In the example above, it sees that Counter objects are produced by data and consumed by incrementTheory, so it executes incrementTheory once for each element in the array returned from data.

Theories decouple test inputs from test implementation. Data points are automatically reused across multiple theories (even in subclasses), making it easier to write new tests. Adding a data point often provides a value that a test writer may not have originally considered, thus improving all Theories that use the data point.

But certain data points may not be applicable to a particular Theory. The test writer describes what data points apply by using methods provided by the org.junit.Assume class. Assumptions are similar to normal assertions except they cause a Theory to skip certain data points rather than fail. In our example, incrementTheory should not increment a counter whose value is equal to Integer.MAX_VALUE since the value would overflow. Therefore, incrementTheory uses assumeTrue to check for this special case.

This summary and example briefly describes the basics of Theories but glosses over how Theories work internally and lacks practical advice like how to write "good" theories. I hope that the undergrads and future weblog posts can explore these topics and deeper research issues further.

Notes

  1. See also an early paper on Theories and the initial announcement of their inclusion as part of an experimental project called Popper.
  2. .NET offers a similar feature but calls it—perhaps more descriptively—parameterized unit tests. JUnit uses this term to mean test classes that are instantiated with input data.
  3. Internally, JUnit finds data points whose declared types derive from the declared types of Theory parameters. It does not currently box and unbox primitive data points. I submitted a simple patch that fixes the problem, but it has not yet been accepted.

ReAssert at ASE 2009

In my previous post, I wrote about ReAssert, the tool I built to automatically fix broken unit tests. Yesterday I received notification that the paper describing the tool got accepted to ASE 2009.

This is the same paper mentioned in my crunch time analysis and typography request.

Here is the (working) abstract:

Developers often change software in ways that cause tests to fail. When this occurs, developers must determine whether failures are caused by errors in the code under test or in the test code itself. In the latter case, developers must repair failing tests or remove them from the test suite. Fixing tests is time consuming but beneficial, since removing tests reduces a test suite's ability to detect regressions. Fortunately, simple program transformations can repair many failing tests automatically.

We present ReAssert, a novel technique and tool that suggests repairs to failing tests' code which cause the tests to pass. Examples include replacing literal values in tests, changing assertion methods, or replacing one assertion with several. If the developer chooses to apply the repairs, ReAssert modifies the code automatically. Our experiments show that ReAssert can repair many common test failures and that its suggested repairs correspond to developers' expectations.

The conference will be held in Auckland, New Zealand. I am excited to travel overseas to present my work. Vilas, my coauthor, and Yun-Young, my officemate, are both from New Zealand and are eager to visit home.

Update September 8, 2009

I have posted the final version of the paper and updated the ReAssert homepage.

Update November 30, 2009

The conference presentation went very well, and I got a great deal of insightful questions and feedback from other attendees. Here are the presentation slides. I told the story of Alice the software developer like in the previous ReAssert post. The presentation starts with a picture of Alice adapted (as per Creative Commons) from xkcd #662.

Alice the software developer. Adapted from xkcd #662 and used in my ReAssert presentation.

I had originally planned to draw a picture in my normal cartoon style, but decided instead to use something simpler. The xkcd picture turned out to be a good choice; it made the audience laugh, and one attendee mentioned Scott McCloud's assertion from Understanding Comics that a simple face causes the audience to identify themselves in a character.

Lego Siebel Center

I recently read that Lego released models of The Guggenheim and Fallingwater as a part of its new "Architecture" series. That news inspired me to design a Lego version of the University of Illinois' Thomas M. Siebel Center for Computer Science.

Lego Siebel Center facing southwest

I cannot comment on how Siebel Center's architecture compares to The Guggenheim or Fallingwater, but the building has some interesting features that were a challenge to translate into Lego. In particular, choosing the correct scale, building the angled sections, and sculpting the topology of the courtyard took a lot of experimentation. Fortunately, Siebel Center is one of the most photogenic buildings on campus, so the web is filled with pictures that I could reference [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].

The key to figuring out an appropriate scale came from this detailed floor plan. I needed a scale that provided a good level of detail, allowed walls and other structures to be subdivided into "nice" Lego sizes, and produced a model of reasonable size. As is often the case, the simplest solution was the best: if I used a single 1×1×1 block for each window, then everything fell together like magic. At this scale, the full model is about 70 studs (≈22 inches) long by 60 studs (≈19 inches) wide. I have not yet measured the actual size of Siebel Center's windows to determine the Lego-to-real life scale.

I started with the western wall of the building since it is a sheer face of brick and windows and I had a picture reference handy. From there, I continued roughly counterclockwise until I reached the glass-faced northern facade which angles out from the main body of the building. I built this pie-shaped section separately and slid it into place against an otherwise blank wall. Many angled "wing" pieces hide the gap.

A patio sits in a depression at the bottom of the angled section. I first attempted to orient the depression to the main building and rest of the courtyard but found that the grass and stairways did not meet the patio nicely. Instead, I connected the slope to the patio and slid the slope under the rest of the grass using stubless plates.

You can view the digital model in Lego Digital Designer. I would love to build the model in real life, but according to LDD, it would cost around $850. I could probably reduce the price by refining the design and buying bulk pieces. Maybe the computer science department could sponsor its construction?

The following images show the completed design. There are more perspectives in the gallery.

Lego Siebel Center facing southeast
Lego Siebel Center facing northeast
Lego Siebel Center facing northwest

Google Games 2008

Last Saturday, the Google Games returned to UIUC. Like last year's games, teams of five had to solve puzzles and build a device using Lego blocks. The organizers changed and improved the games by starting with a trivia contest, removing the long athletic event, and adding a second puzzle session. Lucas, Sam, Zack, and I resurrected Team YAY!, and Josh filled in for Wade who was out of town. We did better than last year, but failed to win a prize.

The trivia contest had three categories: "Computer Science", "Math", and "Geek Trivia". A rotating panel of contestants from different teams had to provide questions for Jeopardy-style answers like, "This programming language was named after a French mathematician and philosopher", "93", "This person invented Tetris". It is unfortunate that we had to answer (question) individually since at least one member of Team YAY! knew the answer (question) to every question (answer). Despite that, Zack propelled us to the lead when he knew the answer (question) to "This was Sega's original name".

The puzzles were more varied and required less brute force than last year. We were given two programming problems, a tesselation question, a variation on Sudoku, two graph traversal problems, a faulty network puzzle, and a paper-folding task, among others. I tackled the programming problems. In the first session I had to determine what characters three convoluted functions printed. Lucas solved the function written in Logo that drew its characters. I solved the other two functions written in Python and C that involved deep recursion and factoring polynomials, respectively. In the second session I had to determine what conditions defined several sets of numbers (for example, x is a third power) and then find several additional numbers that satisfied multiple conditions (for example, x is a third power containing the number 4).

We solved the required five out of six questions in the first session, but only three in the second.

For the Lego contest we had to build a trebuchet that could throw a small Lego tire into a bucket eight feet away. Each team was given a bag of standard Lego blocks and a one-pound fishing sinker to use as a counterweight. I was unable to build since I was busy with the programming questions, but I still found the task particularly interesting for two reasons. First, unlike many throwing contests, we were judged on accuracy rather than distance. That factor definitely affected the designs. Second, like last year's bridges, Lego bricks do not naturally lend themselves to building a war engine. Several teams had ingenious ways of reinforcing the throwing arm, but most, including our trebuchet, failed to hit the bucket.

Our trebuchet and the second set of puzzles caused us to fall from our initial lead. Vilas and Alejandro's team, Four Normal People and a Nerd, completed the contest in 3 hours 46 minutes, winning faster than the teams at MIT, Harvard, Berkeley, and Stanford. Even though we did not win this year, all of us enjoyed the games. I was pleased to see that Google improved the organization and content according to last year's feedback.

Qual Exam (Update: Passed!)

The qualifying examination is the grueling test that all PhD. students must pass before starting their theses. I had mine last Tuesday.

All qual exams are different. My friends in Systems had a huge reading list; a friend in Numerical Methods had to be able to answer almost any question on computer science theory. For the software engineering qual, I had to present and critique two papers in detail and be able to answer almost any question about the papers' main ideas and related work.

My two papers were the following:

  • The JastAdd Extensible Java Compiler by Torbjörn Ekman and Görel Hedin in OOPSLA 2007

    The JastAdd Extensible Java Compiler is a high quality Java compiler that is easy to extend in order to build static analysis tools for Java, and to extend Java with new language constructs. It is built modularly, with a Java 1.4 compiler that is extended to a Java 5 compiler. Example applications that are built as extensions include an alternative backend that generates Jimple, an extension of Java with AspectJ constructs, and the implementation of a pluggable type system for non-null checking and inferencing.

    The system is implemented using JastAdd, a declarative Java-like language. We describe the compiler architecture, the major design ideas for building and extending the compiler, in particular, for dealing with complex extensions that affect name and type analysis. Our extensible compiler compares very favorably concerning quality, speed and size with other extensible Java compiler frameworks. It also compares favorably in quality and size compared with traditional non-extensible Java compilers, and it runs within a factor of three compared to javac.

  • ILEA: Inter-Language Analysis across Java and C by Gang Tan and Greg Morrisett in OOPSLA 2007

    Java bug finders perform static analysis to find implementation mistakes that can lead to exploits and failures; Java compilers perform static analysis for optimization. If Java programs contain foreign function calls to C libraries, however, static analysis is forced to make either optimistic or pessimistic assumptions about the foreign function calls, since models of the C libraries are typically not available.

    We propose ILEA (stands for Inter-LanguagE Analysis), which is a framework that enables existing Java analyses to understand the behavior of C code. Our framework includes: (1) a novel specification language, which extends the Java Virtual Machine Language (JVML) with a few primitives that approximate the effects that the C code might have; (2) an automatic specification extractor, which builds models of the C code. Comparing to other possible specification languages, our language is expressive, yet facilitates construction of automatic specification extractors. Furthermore, because the specification language is based on the JVML, existing Java analyses can be easily migrated to utilize specifications in the language. We also demonstrate the utility of the specifications generated, by modifying an existing non-null analysis to identify null-related bugs in Java applications that contain C libraries. Our preliminary experiments identified dozens of null-related bugs.

I will learn if I passed in a week or two. I feel my presentations went well, though I am still reliving the questions that I was unable to answer.

Update: 3/5/08

I passed unconditionally! I am officially a PhD. student.

Accepted!

The FSE paper got accepted! We got a lot of great comments from the reviewers, so for the next few weeks we will make the final changes to ready the paper for publication. Publication! I'm going to Croatia!

ICSE 2007

Last week I passed another grad school milestone: I went to ICSE 2007, my first research conference.

I do not think I could have had a better first conference. ICSE is one of the top three or four software engineering conferences in the world, and attracts some excellent submissions. I arrived Tuesday night and spent the next four days listening to many interesting talks (and, of course, a few boring ones) and networking with other researchers. I saw too many great ideas and met too many smart people to describe in this short weblog post; check out the list of papers and presenters if you are interested.

We spent most of our time in the hotel conference center, but I did get a chance to see some of the rest of Minneapolis. On Thursday, the conference dinner was held at Nicollet Island, a historic park in the middle of the Mississippi River. There, one could try hatchet throwing, archery, or a Segway. I hit the hatchet target after only three tries, but did not get a chance to shoot an arrow or ride a Segway because the Minnesota cold drove me back indoors. Has my short time in California made me so thin-skinned?

On Saturday night, after a long day at the Automated Software Test Workshop, I went with a small group to the Mall of America. We ate dinner at a completely ridiculous rainforest-themed restaurant whose walls were covered in jungle foliage and animatronic animals with servers dressed as safari guides. After that, we walked around, basking in the glow of American consumerism.

Google Games and Legos

Last weekend Lucas, Sam, Zack, Wade, and I participated in the first annual Google Games at UIUC.

The were three main events: puzzles, Lego bridge building, and a Wii tournament. For the puzzle event, the organizers gave each team an envelope containing six problems to solve. Our team started out well—I was the first to complete a paper-folding puzzle, and we quickly completed two others— but we failed to complete the final three. One was a Sudoku variant in which we had to fit the letters GOOGLE into a hexagonal grid. Another was a logic puzzle in which we had to determine from a set of clues where people lived on a map. I had completed three of four programming sub-problems involving loop expansion when time ran out.

Unfortunately, we were not allowed to keep the puzzles, and the organizers never announced the correct answers. No doubt they wanted to keep people like me from posting the questions and answers online, but, still, it would have been nice to experiment with the questions at home.

We lost in the first round of the Wii tournament, so while the other teams competed in Wii tennis, we played ping-pong in another room.

I thought the Lego bridge building was the most interesting part of the games. We had to build a bridge that the organizers would judge based on aesthetics and strength. I had to span 24 stubs, rise at least four blocks high, and allow an eight-stub-wide car to cross it. In addition, we had only a set number of basic Lego pieces (no Technics), and could only trade pieces with an equal number of stubs.

Unfortunately, we did not have a cohesive plan for our bridge and ended up with a very, very disappointing and ugly mess that I am ashamed to admit I had a part in building. However, the problem is certainly interesting: how can one build a weight-bearing structure out of materials that perform very poorly under tension? The winning team's bridge held 102 pounds because the core of their main span consisted of 2x6 plates turned on their side. This is an excellent idea, and it got me thinking of other possible designs.

Last night I downloaded the Lego Digital Designer and started building bridges. I feel the following would hold a lot of weight:

The main span is modeled after floor joists. It is made up of laminated 2x8 plates connected at the joints with 2x2 blocks. These long plates perform very well under tension, and the 2x2 blocks prevent twisting and "delamination". The span rests on footings made of normal 2x4 and 2x2 blocks. The green 1x4 blocks keep the span from sliding off the footings and help prevent the footings from falling over.

I know a few engineers read this website; what do you think of the design? I have posted the Lego Digital Designer model file if you would like to play with it.

Publication

Last Monday I passed an important milestone in my graduate career: I submitted my first paper for publication. It is called "Automated Testing of Refactoring Engines", and we submitted it to FSE 2007. The project website contains our bug reports and experimental data.

I am very excited about this paper. Not only is it the culmination of the work I have been doing since last August, but I was fortunate enough to be first author. I feel we have some very strong results and a great point from which to continue future work. Now we need to forget about this submission and concentrate on the next conference.

Update

The paper was accepted!

Illinermaker

I am now an Illinermaker (or would that be Boillini?). I have completed my move from Purdue to the University of Illinois and have spent the last four days settling in and preparing for the semester.

Me wearing a Purdue jacket over an Illinois shirt

The apartment is furnished, so the move was easier than it would have been had I kept my table, couch, and desk. I brought the table home to go into storage until my family or I have need for it. We did not just get rid of it because, in the Sue's words, "That was your grandmother's first table." The couch went outside to be picked up by a former coworker. I hope he got it; he was in the middle of a family emergency as I was moving out. If not, that couch certainly had a good run. It remained comfortable and clean through one bedroom, three dorm rooms, one apartment, and four moves. Finally, the desk went to Doug who wrestled that 6-foot monster into his new apartment at Purdue. Since I had such a huge desk at the old apartment, I think the universe needed to restore balance by giving me a really really tiny desk at my new apartment. It has just over half the surface area of the old desk. Aside from the small desk, I am very pleased with the new apartment. It is clean, quiet, as close to campus as I can get, and has many of the conveniences and appliances of a larger apartment.

I am going to be a research assistant for Professor Darko Marinov's group this semester. That means I will not have to grade undergraduate work like I would if I was a teaching assistant, but I will have to do a whole lot more programming, reading, and other "research"-ey things. I do not know yet what I will be working on, but it will probably involve software testing and automated program generation. I will write about that and the classes I am taking when I know more.

I am ready and eager to start what my father accurately called, "the next chapter of my life".

Decision

It is official: I am going to Illinois in the fall. Everything I have read about UIUC's department and everything I saw last week has convinced me that it is the right place to go. That, and I hate having unresolved decisions hanging over my head. I faxed the acceptance letter after classes today.

Update: 3/24/06

I finally got a response from Texas: they regret to inform me that they are not recommending me for admission. I also got confirmation that my UIUC admission acceptance arrived successfully. So, with my curiousity satisfied and my conscience clear that I made the right choice, I close the book on my graduate school admissions saga.

University of Illinois Visit

I got rejection emails from MIT, Carnegie Mellon, and, surprisingly, Purdue. I was getting discouraged and a bit scared when I got my first acceptance email from the University of Illinois at Urbana-Champaign. That first line: "It's my pleasure to congratulate you..." eliminated all worry and made me jump out of my chair in excitement. You may remember that UIUC has always been near the top of my list. Soon after receiving UIUC's email, Wisconsin-Madison's arrived. It said I could come, but they would not give me any money if I did. I am still waiting on Texas-Austin.

Last weekend I went to the UIUC CS department's Prospective Graduate Student Weekend. They put 14 other CS students and me up in a hotel and tried to woo us to the department just like we tried to woo them a few months ago.

I arrived in the midafternoon on Saturday and found a fire truck in the hotel parking lot. I learned from the front desk that the sprinklers had gone off, soaking a maid with stagnant water and turning a stairwell into a waterfall. I checked in amidst the excitement, then wandered around campus for a while.

Even though Illinois and Purdue have a comparable number of students, Illinois' campus seemed much larger. The buildings appeared to have more floors (perhaps because half of Purdue is underground) and tree-lined malls seemed to spread them out more. I walked from one end, where all the engineering and technical students spend their time, to the agricultural greenhouses near a large cemetery, then back through the liberal arts section. Oddly, the campus is peppered with random farm houses tucked in between hulking red brick buildings. I forgot to get my camera out of the car before walking around, but you can find other peoples' pictures of the campus here.

In the evening, the other prospective students and I went to a pizza social with current CS grad students. The event was held in the ground floor of UIUC's new CS building, the absolutely beautiful Siebel Center. I networked admirably with a small handful of graduate students and briefly with Darko Marinov, a new professor in the software engineering group with whom I had exchanged a few emails.

My name on the big screen in Siebel Center

My name on the big screen in Siebel Center

Later that evening, a few of the prospective students and I were planning to go to Green Street, the main entertainment strip through the campus, but pelting rain forced us to the restaurant near the hotel instead. The six of us then embarked on the absolute best bull session I have ever had. We made fun of our (and each other's) undergraduate schools, talked about CS, and generally had a merry time for several hours.

The organizers filled Sunday to the brim. In the morning we listened to professors talk briefly about the various areas of study available in the department. Then we had a surprisingly informative question-and-answer session with a panel of professors. After lunch, we split off to go to individual meetings with professors. I talked with Professor Marinov about automated refactoring tools, automated exhaustive unit testing techniques, and programming languages for use in testing, all topics that I can assure you are much more interesting than they may sound.

Lunch in Siebel Center

Lunch in Siebel Center

I had a bit of time to burn after that, so I joined some of the theory group graduate students who were talking with an impromptu group of prospective students in a lounge area. At one point Steve LaValle, the main host of the weekend, brought out a three-wheeled scooter that could travel at about the pace of a relaxed jog when the rider rotated the handlebars correctly. Those of us in the lounge took turns racing it around the second floor with varying degrees of success. Professor LaValle said that he had bought the scooter with research money to find out if its method of propulsion could be applied to his field of robotics.

Steve LaValle with the scooter (apologies for the blurriness)

Steve LaValle with the scooter (apologies for the blurriness)

At around 4:00 the prospective students reconvened for a building and campus tour. My group had an unfortunately shy and reticent guide, but we saw a bit more of Siebel Center and the northern part of campus.

Touring Siebel Center

Touring Siebel Center

A memory core from ILLIAC

A memory core from ILLIAC

View from the second floor of Siebel Center

View from the second floor of Siebel Center

A strange mannequin in the server room that was apparently used for wearable computing applications

A strange mannequin in the server room that was apparently used for wearable computing applications

The whiteboard in the server room

The whiteboard in the server room

We finished the evening with dinner at a plush Italian restaurant in Champaign.

I reflected on the weekend during my two hour drive back to Purdue that night. It was difficult last semester and last year to decide that I wanted to pursue graduate school. I have a good deal of work experience from my summer internships, and I would not have had a problem finding a job if I chose. Would I be capitalizing on that experience as much as I could if I went to graduate school? Speaking to professors and current graduate students this weekend gave me a clearer view of what my next few years in graduate school may contain. I am sure I will work harder and longer than I ever have before, but it will be on the bleeding edge of the area I choose. Nowhere will I have the opportunity to expand myself and my chosen craft more than in an institution like UIUC. Whether I end up there or at UT, I am convinced that graduate school is where I need and want to be at this point in my life.

Semester Projects Part One

I expected this to be a light semester. I knew it might get busy from time to time, but I certainly could not have foreseen the constant, unremitting load of work that I have borne like an overworked pack mule for the entire semester.

In previous semesters, I have been fortunate to have at most two major projects going at any one time. They might overlap for a week or two, but overall, I have had periodic bursts of heavy work separated by lighter—but certainly not empty—spells. This semester has been different. This semester I had three major projects spanning the entire three and a half months since summer ended.

It has been tough, but all three projects are complete, turned in, and/or demoed. I plan to write about each of them in the order they concluded, starting with...

Project One: Graduate School Applications

I have heard it said that applying to medical school is the equivalent of a three credit hour college course. If that is the case, then applying for a Computer Science graduate degree counts for at least a two credit hour seminar. I wish I could have hired a secretary to handle all the papers, requirements, forms, and pages and pages of thorough yet misleading instructions.

Of the three projects, this has lasted the longest. I knew I wanted to go to graduate school around sophomore year. Much of my CS work—such as undergraduate research and the CS honors program—has been to prepare for further study in addition to a career. Last summer I seriously started looking at schools and began researching what I would have to do to apply. I started the online applications about a month into the semester, and I took the GRE in October.

The GRE is a computer-adaptive test, meaning that the questions get harder as one progresses. The increase in difficulty was very noticeable because I started having to guess a lot about halfway through each section of the test. The adaptive nature of the test also makes it very short—only about three hours total—so time plays a large factor in completing the sections. These two things made the test much more stressful than a normal multiple choice test. Taking the test on the computer was beneficial, however, because I got my verbal and math scores as soon as I finished. I did reasonably well.

The application process sped up after I took the GRE. I completed my statement of purpose in an afternoon, and three current and former course instructors agreed to write letters of recommendations around that time.

I applied to the following six schools:

All are top-20 computer science graduate schools, and I am sure I would be happy wherever I end up. I plan to get my master's degree in computer science, but at the advice of several people, I am applying as a PhD. student. This will help my chances of getting accepted and will probably open up opportunities for working on more interesting projects. It will also make it easier to continue for four years if I decide to get my doctorate.

It was interesting to note the similarities and differences between the schools' application processes. I was pleased to find that every school had an online application. I only had to send my paper transcripts to each school and a paper application to the computer science department at UT.

Purdue and UIUC both used the same software for their applications. This is interesting because the schools are so similar in other respects: both are highly-respected, technological, Midwestern schools. Fittingly, the software was equally bad in both cases.

MIT had the best application. It was easy to use, it gave clear instructions, it did not use popups (UIUC's was three popups deep at one point), and it worked in Firefox. The only downside was that I had to manually type in every CS, math, and science course I have taken as an undergrad.

I submitted each of the applications and mailed the final paperwork about two weeks ago. Now I must leave it up to the faceless application machinery to decide what I am going to do with myself for the next two or more years.