Month: July 2016

What are you building?

A project, a product, or a brand?

Actually, luck has played a big role in our industry, and sometimes you don’t know what you’re building until later. I could have called this post “What’s in a name?” or “Why I have to work around MySQL performance bugs when there’s at least one technically superior and totally free database we could have used instead.”

This is a story of well-meaning people who made what seemed like reasonable choices at the time, some of which have caused mild suffering. They say the road to hell is paved with good intentions.

So what’s in a name? In the 1980’s if you’re a geeky professor creating a project to replace the “Ingres” database project, “Postgres” sounds like a pretty clever name. If SQL becomes a popular standard and is now supported, changing “Postgres” to “PostgreSQL” also seems pretty sensible. There’s continuity. The handful of students who used it at the time were not confused at all. But even for them it might have been better to choose the name of a painter more recent than Ingres (DegaSQL, MatisSQL, PicasSQL, KandinSQL, MonetSQL, RenoirDB, SeuratSQL, DaliBase?).

Then there’s MySQL. Sigh. Maybe we’re all shallow, narcissistic people at heart, or maybe we all just follow the orders of people who are, but “MySQL” is a near-perfect brand name because it’s all about “me“, and it’s “mine”. No need to explain what’s up with the name. Sold. Add to that a focus on the needs of ISP’s and Linux users, and it becomes second only to Oracle in popularity. PostgreSQL is in 4th place now, but the usage scores drop off a cliff after 3rd place (which is Microsoft SQL Server).

It turns out, though, that the brilliant name choice of “MySQL” was just as random as the awful name chosen for its competitor. “Monty” Widenus named MySQL after his first daughter, My. By the way, more-actively-maintained-and-improved fork of MySQL, languishing in 20th place in usage rankings, is MariaDB, named after his second daughter. If he’d had only one daughter, named Ingrid instead of My, the fork might have been called “PostgridSQL”.

So, do I have a point? Just that you might want to think when you create something about who it’s for and to think, when naming or re-branding it, about how people who are not currently “in the loop” will perceive it. Also, if your technology is really solid and well-designed, please be lucky.

For info, recent database usage rankings from db-engines.com:

1. Oracle Relational DBMS 1449.25
2. MySQL  Relational DBMS 1370.13
3. Microsoft SQL Server Relational DBMS 1165.81
4. MongoDB  Document store 314.62
5. PostgreSQL Relational DBMS 306.60
6. DB2 Relational DBMS 188.57
7. Cassandra  Wide column store 131.12
8. Microsoft Access Relational DBMS 126.22
9. SQLite Relational DBMS 106.78
10. Redis  Key-value store 104.49
11. Elasticsearch  Search engine 87.41
20. MariaDB Relational DBMS 34.66

 

Improved matching error messages in Extended-Mockito

I’ve recently made some improvements to Extended-Mockito in the area of failure messages.

In early versions, messages from a failure to match in a verify() call were a bit cryptic, especially when matching based on lambdas.  This is what you used to get :

Wanted but not invoked:
exampleService.doAThingWithSomeParameters(
    <Extended matchers$$ lambda$ 6/ 1 5 0 2 6 8 5 4 0>,
    <Extended matchers$$ lambda$ 8/ 3 6 1 5 7 1 9 6 8>,
    <custom argument matcher>,
    <Extended matchers$$ lambda$ 1 1/ 2 1 0 5 0 6 4 1 2>
);

In the first of my examples with the new improvements (available starting in version 2.0.78-beta.1 of extended-mockito and transitively in version 0.9.0 of tdd-mixins-core and tdd-mixins-junit4 ) it’s now possible to show more clearly what kind of arguments were expected:

Wanted but not invoked:
exampleService.doAThingWithSomeParameters(
{String containing all of: [Butcher,Baker,Candlestick Maker]},
[All items matching the given Predicate],
[One or more items matching the given Predicate],
SomeBean where val1 > 5
);

For info, the expectation call which gives this failure message is:

verify(expecting).doAThingWithSomeParameters(this.containsAllOf("Butcher", "Baker", "Candlestick Maker"),
				allSetItemsMatch(s -> s.startsWith("A")),
				oneOrMoreListItemsMatch(s -> s.startsWith("B")),
				objectMatches((SomeBean o) -> o.getVal1() > 5, "SomeBean where val1 > 5"));

The TestNest Pattern

I discovered the TestNest pattern – the idea of using a suite of nested test classes in order to create a hierarchical organization of tests – in this blog post by Robert C. Martin, but apart from one other article I haven’t found a lot of information online about this technique. So I thought I’d try it out in a sort of hello-world to get a feel for it. As a bonus, I added in some tests using the excellent Zohhak test library which generates automatically nested tests for sets of values via an annotation.

My test class can be found here.

Here are some of the highlights…

The outer class declaration with its JUnit Suite annotations:

@RunWith(Suite.class)

@SuiteClasses({ MyExampleClassTest.Method1.class, MyExampleClassTest.Method2.class,

MyExampleClassTest.Calculation1.class, MyExampleClassTest.Calculation2.class})

public class MyExampleClassTest {

One of the nested classes in MyExampleClassTest is called SharedState. It contains the object under test (called underTest) and is the parent of all the other nested test classes (and it also uses a mixin from tdd-mixins-junit4 which gives all its subclasses the ability to call assertions non-statically).

There are 4 nested classes which contain tests – one for each method in the class under test. This seemed like a logical organization, though it’s not what Uncle Bob did in his aforementioned blog post. It might make sense to further subdivide between happy path tests and weird corner case tests (what Uncle Bob called “DegenerateTests” in his example), and there may be better ways to divide tests than along class and method lines (though I would hope that my classes and methods under test are cohesive units of organization).

Using the Suite runner in the parent class doesn’t prevent you from using other runners in the nested classes. Two of the nested classes use the Zohhak test runner:

@RunWith(ZohhakRunner.class)

I intentionally put 2 failures in the tests (one fail() in a normal test and one error in a Zohhak value set) to see what the failures would look like.

Here’s part of what Maven had to say about these failures:

Failed tests: should_fail(org.example.MyExampleClassTest$Method2): intentional failure to illustrate nested test failure messages

should_calculate_cube [-1, 1](org.example.MyExampleClassTest$Calculation2): expected:<[]1> but was:<[-]1>

Here’s what I see in Eclipse’s JUnit sub-window:

Eclipse JUnit run results showing 2 nested errors

This seems like a minor improvement over long, descriptive test method names for quickly getting a feel for where the problem isespecially when there are multiple simultaneous failures. I didn’t have to put the name of the method under test in the test method name, and in the eclipse JUnit runner UI the tests for each method are nicely grouped together.  Zohhak works well with this approach, as well (and seems like a pleasure to use in general for testing calculation results).