Friday, March 30, 2018

Hardback Review

Received my Hardback copy that I Kickstarted. Having played Paperback once or twice, the thought of an evolved version piqued my interest. Here's an initial take after an unboxing and one game: I loved this playthrough, and I'm looking forward to the next one!

Press your luck - In most deck builders, your hand is your turn. A bad draw leads to an unsatisfying nothing turn. Not so with Hardback. Use ink and remover to turn a bad draw into a high dollar buy. I like that drawing cards (a coveted power in Dominion and Star Realms) is a core mechanic rather than in the soup of card benefits.

The power of not buying - In most deck builders, you need to buy something by the end of your turn. Use it or lose it. Adopting this in Hardback can lead to filling your deck with trash letters (L. Ron Hubbard syndrome) and a perennial lack of money. Instead, go for quality by NOT buying cards and instead buying ink. This allows you to play ACROSS turns by saving up ink, drawing all your cents next turn, and dropping it on that sweet consonant or Perennial Classic with great benefits. Once we realized this, play went a lot faster as we could buy high cost cards. We just had to wait and plot and plan.

A Game About Words - Our first game was with 3 people: one experienced gamer, one apathetic adult, and one ADHD preteen. I was worried that, like Scrabble, the word part of the game would turn players off. Instead, it provided fun stories and interesting interactions. You can turn any card into a wild and lose its benefits, so using all your cards can help you, but not as much as the above pressing your luck. I played two words that mean 'toilet' while my tongue-tied son bought "reveal adjacent wild" cards so he could focus on getting points.

Surprisingly and Pleasingly Interactive - There are no attack cards as a benefit in the standard game, but that doesn't mean it's not interactive. When in doubt, Just give up: Ghost Writer let's you play open-hand and rely on other players. They even get ink as a benefit! For a genre rife with negative player interactions ruining games (no-attack Dominion is a staple at our house), this is a refreshing way to add positive interactions. The Perennial Classic mechanic is similarly combative but not adversarial, and the Jail benefit and ability to reset the offer row can elicit a groan or two while you foil your opponents' plans.

OMG The Design There are puns everywhere, the cards are complex but not cluttered, the cardstock is pleasing to hold, and the use of meeples rather than tokens makes it chunkier than the small box lets on. Leaving room in the box for more cards might hint at expansions, but it comes with plenty of alternative ways to play. I can't wait to break out the player powers and co-op mode.

I know Paperback was hard to get for a while. If you have a chance and need a deck builder with less combat and more pithy reveals, get Hardback.

Link to Reddit discussion:

Inquisitor Eisenhorn

Recently finished painting the Inquisitor Eisenhorn 30th Anniversary figure. As he was one of my father's favorite characters from Dan Abnett's 40k works, he will lead the reliquary squad to guard his urn in my display case!  Most of the techniques are standard, but I learned two things.

The first is that faces are really difficult without the right colors. I couldn't get the blending right with the washes and pots I had. The end result was muddy and pale. I touched it up after some research, and he looks better as a result. The hooded eyes ensure that the genetic anomaly called Private Dickard Syndrome doesn't affect Eisenhorn too. A little grey dry brushing on his chin gave him the 5 o'clock shadow and a little depth to match his hair.

The second bit of learning was around highlighting armor. Because he has so little, I didn't get sick of it and give up. The teal shoulder pads were a dream. They are a very simple highlight that allowed me to build up a rich color. The sharp white highlight was carefully applied, and it makes it look shiny without having to apply a lustrous enamel. I like it so much that the rest of the reliquary squad will have this color on their Tempestus breastplates.

Overall, I like one shot characters like this to learn new techniques. And this figure has enough detail to try many more. I particularly enjoyed the base with its cracked emblem and shiny brass.

Tuesday, March 20, 2018

Behat AfterScenario, PHP Garbage Collection, and Singletons

In Behat, I added a singleton to our contexts to store things across scenarios, but I ran into trouble when trying to keep separation between my tests.  The storage object allowed me to be creative with builders, validators, and similar ways of reducing repetition and making the PHP code behind easier to read.  There was a problem though: it would randomly be cleared in the middle of a test.

The only thing I knew was the object would get cleared at relatively the same time.  I had a set of about 50 different tests in a single feature.  This would call an API multiple times, run validations on the responses, and then move on to the next test.  All the while, it would put information into the storage object.  The test would not just fail in the middle of a scenario, it would generally fail near the same part of a scenario every time.  it was timing, an async process, or something was clearing a logjam.

While designing the storage object, I had the bright idea to clear it with every scenario.  The singleton acts like a global variable, and a clear after each one would ensure data from one test didn't pop up in another.  To make sure i was running this at the last possible moment, I put the clear into the __destruct() method of my context class.  By putting the clear in the destructor, I gave PHP permission to handle it as it saw fit.  In reality, it sometimes left my scenario objects to linger while running the next (due to a memory leak or similar in Behat itself, or a problem in my code; I couldn't tell).

 * Destructor
public function __destruct()

I first stopped clearing the store and the bugs went away.  Whew!  But how could I make sure I wasn't contaminating my tests with other data and sloppy design?  I tried two things:

1) gc_collect_cycles() forces the garbage collector to run.  This seems to have the same effect of stopping the crashes, but it was kind of a cryptic thing to do.  I had to put it in the constructor of the Context rather than something that made more sense.

 * FeatureContext constructor.
public function __construct()
 * Bootstrap The Store
 ApiContextStore::create(); // Creates an instance if needed
2) Putting in an @AfterScenario test provided the same protection, but it ran, purposefully, after every test was complete.  I'm not freeing memory with my clear, so relying on garbage collection wasn't a priority.  I just needed it to run last.

 * @AfterScenario
 * Runs after every scenario */
public function cleanUpStore()

Monday, March 5, 2018

Postman Master Class Pt. 1

I gave a talk on using Postman while testing. We covered the UI, creating a collection, working with environment variables, and chaining tests with JavaScript.

A big surprise from this talk was how few testers knew about Postman to begin with. When I first started testing websites, I wanted a more reliable way of submitting http requests. The ability to save requests got me out of notepad and command-line cURL. The move to microservices only made it more useful to me.

By far, the biggest discovery was how many testers there were that had never explored its signature features. Environments and scripting make the instrumentation of integration testing almost effortless. Organizations that want automation but don't want to give the time can turn simple tests into bare bones system tests for very little further expense.

I'm planning a Part 2 where I can talk about Newman, the command line collection runner. I also want to demonstrate the mocking and documentation features. If a company adopts their ecosystem, it has the potential to make a tester's life much easier.  Even if it's only a tester's tool, it can help them communicate better with developers and reach into the product with greater ease.