Let's Code Jumi

Shows since day one the development of a test runner to surpass JUnit as the de facto test runner on the Java platform. Programming is done with TDD, with the unit-level TDD driven by end-to-end level TDD.

  • Episodes355
  • Total length156 h 51 min
  • Latest episode2015-03-20

Episodes

Project Setup
Let's Code Jumi #1: Project Setup (Part 1) MP4

Jumi is my latest side project and it will be a test runner for the JVM. Its short-term goals are to run tests faster (via parallelism, class loader caching, heuristics and stuff), provide a better user experience than existing test runners, and to overcome limitations of JUnit's test runner which cause an impedance mismatch with for example most of Scala's testing frameworks. Jumi's long-term goal is to be supported by every build tool and IDE, and to surpass JUnit as the de facto test runner on the JVM.

I'll be documenting the development of this app as screencasts also for the purpose of being some research material (I know some researchers at the University of Helsinki who are interested in it). The resolution is higher (1920x1200 vs. 1440x1080) and font smaller (14 vs. 16) than in my previous videos, to make it more practical for me to do programming. Also I will try to optimize my release process so that I can release episodes faster with less effort. For example I will minimize post-production, and write a new name and description only for each theme instead of each episode.

Here is the first episode. Enjoy!


Creating a multi-module Maven project structure and using end-to-end tests to test-drive the build configuration, especially some unusual build requirements (i.e. putting a JAR in a JAR and hiding external dependencies).

Let's Code Jumi #2: Project Setup (Part 2) MP4
Let's Code Jumi #3: Project Setup (Part 3) MP4
Let's Code Jumi #4: Project Setup (Part 4) MP4
Let's Code Jumi #5: Project Setup (Part 5) MP4
Let's Code Jumi #6: Project Setup (Part 6) MP4
Let's Code Jumi #7: Project Setup (Part 7) MP4
Let's Code Jumi #8: Project Setup (Part 8) MP4
Let's Code Jumi #9: Project Setup (Part 9) MP4
Let's Code Jumi #10: Project Setup (Part 10) MP4
Let's Code Jumi #11: Project Setup (Part 11) MP4
Let's Code Jumi #12: Project Setup (Part 12) MP4
Walking Skeleton - Running Zero Tests
Let's Code Jumi #13: Running Zero Tests (Part 1) MP4

Creating a walking skeleton to get the project started. We will start with an end-to-end test of running an empty test suite, which will drive the design for communicating with the daemon process.

Let's Code Jumi #14: Running Zero Tests (Part 2) MP4
Let's Code Jumi #15: Running Zero Tests (Part 3) MP4
Refactoring - Message Passing
Let's Code Jumi #16: Message Passing (Part 1) MP4
Let's Code Jumi #17: Message Passing (Part 2) MP4
Let's Code Jumi #18: Message Passing (Part 3) MP4
Let's Code Jumi #19: Message Passing (Part 4) MP4
Let's Code Jumi #20: Message Passing (Part 5) MP4
Let's Code Jumi #21: Message Passing (Part 6) MP4
Walking Skeleton - Public API
Let's Code Jumi #22: Public API (Part 1) MP4

We continue with an end-to-end test for executing one passing test. This requires writing a minimal testing framework for executing the dummy tests, which in turn drives us to create most of Jumi's public API.

Let's Code Jumi #23: Public API (Part 2) MP4
Let's Code Jumi #24: Public API (Part 3) MP4
Let's Code Jumi #25: Public API (Part 4) MP4
Let's Code Jumi #26: Public API (Part 5) MP4
Let's Code Jumi #27: Public API (Part 6) MP4
Let's Code Jumi #28: Public API (Part 7) MP4
Let's Code Jumi #29: Public API (Part 8) MP4
Walking Skeleton - Running One Test
Let's Code Jumi #30: Running One Test (Part 1) MP4

Using the previously written public API to write the minimal testing framework, until it can report tests which it finds. Then making the end-to-end test of running one test pass with the simplest possible implementation.

Let's Code Jumi #31: Running One Test (Part 2) MP4
Let's Code Jumi #32: Running One Test (Part 3) MP4
Let's Code Jumi #33: Running One Test (Part 4) MP4
Refactoring - Actor Model
Let's Code Jumi #34: Comparable TestId MP4

Some simple refactorings before we start implementing the actor model. Using immutable collections from Functional Java simplifies some code and requires TestId to implement Comparable.

Let's Code Jumi #35: Actors (Part 1) MP4

Though it was possible to make the previous end-to-end test pass without an actor model, it's in a desperate need of one, so now would be a good time to create it.

Let's Code Jumi #36: Actors (Part 2) MP4
Let's Code Jumi #37: Actors (Part 3) MP4
Let's Code Jumi #38: Bug Fixes MP4

A bug in the Shade Plugin's configuration had slipped unnoticed for quite some time, so let's improve the build tests to be stricter about the contents of the build artifacts. Also a bug fix and some improvements to the TestId.compareTo() method.

Let's Code Jumi #39: Actors (Part 4) MP4
Let's Code Jumi #40: Actors (Part 5) MP4
Let's Code Jumi #41: Dynamic Events (Part 1) MP4

I had a short up-front design session to figure out what actors the system will need. Many new interfaces will be needed for actor-to-actor communication and the current way of writing the event classes by hand will not scale. I will at first write a reflection-based solution for producing those events, because I can do that faster than it would take to figure out how to do compile-time code generation.

Let's Code Jumi #42: Dynamic Events (Part 2) MP4
Let's Code Jumi #43: Dynamic Events (Part 3) MP4
Let's Code Jumi #44: Dynamic Events (Part 4) MP4
Let's Code Jumi #45: Dynamic Events (Part 5) MP4
Let's Code Jumi #46: Multi-Interface Actors (Part 1) MP4

After starting to write the new actors, there comes the need for actors with multiple interfaces - or multiple actors in the same thread, however you want to think about it.

Let's Code Jumi #47: Multi-Interface Actors (Part 2) MP4
Let's Code Jumi #48: Multi-Interface Actors (Part 3) MP4
Let's Code Jumi #49: Multi-Interface Actors (Part 4) MP4
Let's Code Jumi #50: Multi-Interface Actors (Part 5) MP4
Let's Code Jumi #51: Actorified Runners (Part 1) MP4

Converting the application to be actor-based. The TestRunCoordinator class which remains from the walking skeleton (written in episode 33) needs to be replaced with actor-based suite and test class runners.

Let's Code Jumi #52: Actorified Runners (Part 2) MP4
Let's Code Jumi #53: Actorified Runners (Part 3) MP4
Let's Code Jumi #54: Actorified Runners (Part 4) MP4
Let's Code Jumi #55: Actorified Runners (Part 5) MP4
Let's Code Jumi #56: Actorified Runners (Part 6) MP4
Let's Code Jumi #57: Actorified Runners (Part 7) MP4
Let's Code Jumi #58: Worker Threads (Part 1) MP4

Implementing the actor-based runners got too complicated, but I have a hunch that it would be easier to implement them if I would have a simple way to start worker threads. They would run unattended after started and have a callback of when they finish. So let's improve the actor infrastructure.

Let's Code Jumi #59: Worker Threads (Part 2) MP4
Let's Code Jumi #60: Worker Threads (Part 3) MP4
Let's Code Jumi #61: Single-Threaded Actors (Part 1) MP4

Creating a second implementation of the Actors class which will be single-threaded and useful for unit testing. I will use abstract contract tests for the common behaviour which must work with both threading models. Also some tests need to be refactored to decoupled them from the threading model.

Let's Code Jumi #62: Single-Threaded Actors (Part 2) MP4
Let's Code Jumi #63: Single-Threaded Actors (Part 3) MP4
Let's Code Jumi #64: Refactoring Actor Tests (Part 1) MP4

Putting the single-threaded actors into use and cleaning up the actor tests by extracting recurring abstractions. Also trying out an idea about extracting details into a super class which I read about recently.

Let's Code Jumi #65: Refactoring Actor Tests (Part 2) MP4
Let's Code Jumi #66: Refactoring Actor Tests (Part 3) MP4
Let's Code Jumi #67: Refactoring Actor Tests (Part 4) MP4
Let's Code Jumi #68: Actorified Runners (Part 8) MP4

Finishing the work on the new actor-based runners, now that the actor framework has been improved to better match their needs.

Let's Code Jumi #69: Actorified Runners (Part 9) MP4
Let's Code Jumi #70: Actorified Runners (Part 10) MP4
Let's Code Jumi #71: Actorified Runners (Part 11) MP4
Let's Code Jumi #72: Actorified Runners (Part 12) MP4
Let's Code Jumi #73: Actorified Runners (Part 13) MP4
Let's Code Jumi #74: New Domain MP4

I registered the domain jumi.fi so I will need to change all packages and groupIds of the project. The build tests prove their worth once again by reminding about all the places which need to be updated.

Refactoring - Code Generator Maven Plugin
Let's Code Jumi #75: Hello Maven Plugin (Part 1) MP4

After a quick test for the SuiteListener interface, the next big refactoring is to create a source code generator for the event stubs of the actors framework. It should be best implemented as a Maven plugin, which I have never done before, so it will be interesting to find out how to do it.

Let's Code Jumi #76: Hello Maven Plugin (Part 2) MP4
Let's Code Jumi #77: Code Generation (Part 1) MP4

Creating classes which generate the Java source code of the event stubs based on an event listener interface. There will be one factory, one frontend and one backend class for the interface, plus one event class for each method of the interface.

Let's Code Jumi #78: Code Generation (Part 2) MP4
Let's Code Jumi #79: Generating the Factory MP4

Generating source code for the factory class which will instantiate all the other generated classes.

Let's Code Jumi #80: Generating the Frontend (Part 1) MP4

Generating source code for the frontend class which will convert method calls into event instances.

Let's Code Jumi #81: Generating the Frontend (Part 2) MP4
Let's Code Jumi #82: Generating the Frontend (Part 3) MP4
Let's Code Jumi #83: Generating the Backend (Part 1) MP4

Generating source code for the backend class which will convert event instances into method calls.

Let's Code Jumi #84: Generating the Backend (Part 2) MP4
Let's Code Jumi #85: Generating the Backend (Part 3) MP4
Let's Code Jumi #86: Generating the Events (Part 1) MP4

Generating source code for the event classes whose instances will be passed through event queues.

Let's Code Jumi #87: Generating the Events (Part 2) MP4
Let's Code Jumi #88: Maven Plugin Testing (Part 1) MP4

To get started on writing the Maven plugin, we first need some way to write tests for it. I found from Stack Overflow a list of options, of which I will evaluate the alternatives for integration testing: shitty-maven-plugin and maven-invoker-plugin. I choose the latter one and write an integration test using it.

Let's Code Jumi #89: Maven Plugin Testing (Part 2) MP4
Let's Code Jumi #90: Maven Plugin Testing (Part 3) MP4
Let's Code Jumi #91: Maven Plugin Testing (Part 4) MP4
Let's Code Jumi #92: Maven Plugin Testing (Part 5) MP4
Let's Code Jumi #93: Embedded Java Compiler (Part 1) MP4

Our Maven plugin must use the Java compiler to compile the listener interface's source file, because the code generator must be able to use reflection on it. This means fiddling with class loaders and more integration with Maven to find out the project's classpath. Taking a look at the Maven Compiler Plugin is helpful. We will also see how to write post-build verification scripts for the Maven Invoker Plugin.

Let's Code Jumi #94: Embedded Java Compiler (Part 2) MP4
Let's Code Jumi #95: Embedded Java Compiler (Part 3) MP4
Let's Code Jumi #96: Embedded Java Compiler (Part 4) MP4
Let's Code Jumi #97: Embedded Java Compiler (Part 5) MP4
Let's Code Jumi #98: Embedded Java Compiler (Part 6) MP4
Let's Code Jumi #99: Using Code Generator (Part 1) MP4

We can now take our code generator Maven plugin into use, which should weed out the remaining missing features. I also figured out how to configure Maven Invoker Plugin so that we can use JUnit and other libraries in the integration test scripts.

Let's Code Jumi #100: Using Code Generator (Part 2) MP4
Let's Code Jumi #101: Using Code Generator (Part 3) MP4
Let's Code Jumi #102: Using Code Generator (Part 4) MP4
Testing - Thread-Safety Checking Bytecode Enhancer
Let's Code Jumi #103: Parameterized Tests (Part 1) MP4

We need to create a new module for a Java agent, so now that we touch the build tests, it's a good idea to refactor them into parameterized tests. That should make them more maintainable. That will also allow me to write tests for the test data, to make sure that all of the artifacts follow some project principles.

Let's Code Jumi #104: Parameterized Tests (Part 2) MP4
Let's Code Jumi #105: Parameterized Tests (Part 3) MP4
Let's Code Jumi #106: Parameterized Tests (Part 4) MP4
Let's Code Jumi #107: Testing Bytecode Manipulation (Part 1) MP4

I will create a Java agent which does bytecode manipulation to check that non-thread-safe classes (i.e. classes annotated with JSR-305's @NotThreadSafe) are used only from one thread. Unit tests for bytecode manipulation can be written using a custom class loader, which transforms only the bytecode of a selected class, and a bunch of "guinea pig" classes [1] to be used as test data.

[1] See GOOS page 284.

Let's Code Jumi #108: Testing Bytecode Manipulation (Part 2) MP4
Let's Code Jumi #109: Testing Bytecode Manipulation (Part 3) MP4
Let's Code Jumi #110: Testing Bytecode Manipulation (Part 4) MP4
Let's Code Jumi #111: Bytecode Manipulation (Part 1) MP4

The tests are in place, so it's possible to write the actual bytecode transformations. ASM's user guide is a good reference for learning Java bytecode.

Let's Code Jumi #112: Bytecode Manipulation (Part 2) MP4
Let's Code Jumi #113: Bytecode Manipulation (Part 3) MP4
Let's Code Jumi #114: Bytecode Manipulation (Part 4) MP4
Let's Code Jumi #115: Using the Agent (Part 1) MP4

Putting the thread-safety checker's Java agent into real use, which helps to weed out some bugs.

Let's Code Jumi #116: Using the Agent (Part 2) MP4
Let's Code Jumi #117: Generating Line Numbers (Part 1) MP4

The stack traces from the thread-safety checker are missing line numbers for the method which was called from a wrong thread, so let's add those to the generated bytecode.

Let's Code Jumi #118: Generating Line Numbers (Part 2) MP4
Let's Code Jumi #119: Generating Line Numbers (Part 3) MP4
Let's Code Jumi #120: Finishing Touches MP4

Some refactoring to improve thread-safety checker's exception messages before starting to use it.

Let's Code Jumi #121: Hunting Concurrency Bugs (Part 1) MP4

Adding JSR-305 annotations (@NotThreadSafe etc.) and actually finding one concurrency bug, so our doubts were not unwarranted.

Let's Code Jumi #122: Improved Stack Traces MP4

Because of the way how Java shortens chained strack traces, the stack traces in last episode were a bit confusing to read, so let's improve that before continuing with more concurrency testing.

Let's Code Jumi #123: Hunting Concurrency Bugs (Part 2) MP4

Adding the rest of the JSR-305 annotations and doing some performance testing for the thread safety checker.

Walking Skeleton - One Failing Test
Let's Code Jumi #124: One Failing Test (Part 1) MP4

Begin adding support for reporting test failures. Let's first focus on getting just the number of failed tests reported, and leave reporting the stack traces for later.

Let's Code Jumi #125: One Failing Test (Part 2) MP4
Let's Code Jumi #126: Better Mocks (Part 1) MP4

In the last episode there was a test failure with a misleading error message. I will evaluate JMock and EasyMock to see whether they would produce better error messages than Mockito.

Let's Code Jumi #127: Better Mocks (Part 2) MP4

None of Java's three popular mocking frameworks produced as readable error messages as I would like, so let's try creating a hand-written mock.

Let's Code Jumi #128: Better Mocks (Part 3) MP4
Let's Code Jumi #129: Better Mocks (Part 4) MP4
Let's Code Jumi #130: Better Mocks (Part 5) MP4
Let's Code Jumi #131: One Failing Test (Part 3) MP4

Let's see where the end-to-end tests fail next and continue our implementation of failure reporting from there.

Let's Code Jumi #132: One Failing Test (Part 4) MP4
Let's Code Jumi #133: Fail Early MP4

Improving the SpyListener and SingleThreadedActors classes to fail early, to help catching more problems.

Let's Code Jumi #134: One Failing Test (Part 5) MP4

Let's see where the end-to-end tests fail next and continue our implementation of failure reporting from there.

Let's Code Jumi #135: SimpleUnit's Test Reporting (Part 1) MP4

The end-to-end tests were failing because our minimal SimpleUnit testing framework is incomplete - it does not yet execute tests and report test execution events.

Let's Code Jumi #136: SimpleUnit's Test Reporting (Part 2) MP4
Let's Code Jumi #137: One Failing Test (Part 6) MP4

Let's see where the end-to-end tests fail next and continue our implementation of failure reporting from there.

Let's Code Jumi #138: One Failing Test (Part 7) MP4
Refactoring - Code Generator
Let's Code Jumi #139: Better Printing (Part 1) MP4

With the previous feature done, it's a good time to refactor the code generator some. Let's first generate toString() methods for the event classes and improve the code formatting.

Let's Code Jumi #140: Better Printing (Part 2) MP4
Let's Code Jumi #141: Generic Type Parameters (Part 1) MP4

Improving the code generator to produce correct generic type parameters. Even after Java's type erasure it's possible to dig out some type parameter information using reflection.

Let's Code Jumi #142: Generic Type Parameters (Part 2) MP4
Let's Code Jumi #143: Generic Type Parameters (Part 3) MP4
Let's Code Jumi #144: Generic Type Parameters (Part 4) MP4
Let's Code Jumi #145: Builder (Part 1) MP4

Now I can see clearer what the code generator's structure should be like, so let's replace the previous procedural approach with a builder.

Let's Code Jumi #146: Builder (Part 2) MP4
Let's Code Jumi #147: Single-Class Imports MP4

The generated imports can be made a bit more specific, avoiding superfluous imports.

Testing - Mutation Testing
Let's Code Jumi #148: Mutation Testing (Part 1) MP4

PIT is the first user friendly mutation testing framework for Java that I know of. Line coverage is a lousy measure compared to mutation coverage, which actually makes sure that your tests are testing something.

Let's Code Jumi #149: Mutation Testing (Part 2) MP4
Let's Code Jumi #150: Mutation Testing (Part 3) MP4
Let's Code Jumi Special #1: Contract Tests MP4

Trying a more systematic way of creating a new implementation to pass contract tests than what I did a year ago when originally implementing single-threaded actors. See my blog post for more details on this experiment.

Walking Skeleton - Text UI & Stack Traces
Let's Code Jumi #151: Text UI & Stack Traces (Part 1) MP4

Creating a text user interface and changing the end-to-end tests to run against it. Showing exception stack traces in the UI.

Let's Code Jumi #152: Text UI & Stack Traces (Part 2) MP4
Let's Code Jumi #153: Text UI & Stack Traces (Part 3) MP4
Let's Code Jumi #154: Text UI & Stack Traces (Part 4) MP4
Refactoring - Event-Based Text UI
Let's Code Jumi #155: Event-Based Text UI (Part 1) MP4

Creating a more production-ready text user interface which will print results as they arrive, instead of waiting for all tests to finish executing.

Let's Code Jumi #156: Event-Based Text UI (Part 2) MP4
Let's Code Jumi #157: Event-Based Text UI (Part 3) MP4
Let's Code Jumi #158: Event-Based Text UI (Part 4) MP4
Let's Code Jumi #159: Test Names (Part 1) MP4

Improving the new text UI to print the names of tests and their beginnings and endings.

Let's Code Jumi #160: Test Names (Part 2) MP4
Let's Code Jumi #161: Test Names (Part 3) MP4
Let's Code Jumi #162: Use the New Text UI MP4

With the new event-based text UI working, we can replace the old text UI with it.

Testing - Require Thread-Safety Annotations
Let's Code Jumi #163: Require Thread-Safety Annotations (Part 1) MP4

I forgot to add the @NotThreadSafe annotation to TextUI, so let's write a test to make sure I will never again forget that. Those annotations have RetentionPolicy.CLASS so using reflection is not an option and bytecode analyzing is required.

Let's Code Jumi #164: Require Thread-Safety Annotations (Part 2) MP4
Let's Code Jumi #165: Require Thread-Safety Annotations (Part 3) MP4
Let's Code Jumi #166: Require Thread-Safety Annotations (Part 4) MP4
Feature - Running Tests in Parallel
Let's Code Jumi #167: Parallel Execution (Part 1) MP4

It's time to make the system run tests in parallel. We'll write a test class which passes only if its test methods are called in parallel, and then fix one part of the system which accidentally assumed sequential execution.

Let's Code Jumi #168: Parallel Execution (Part 2) MP4
Let's Code Jumi #169: Parallel Execution (Part 3) MP4
Let's Code Jumi #170: Parallel Execution (Part 4) MP4
Let's Code Jumi #171: Refactoring TestClassRunner (Part 1) MP4

The tests are now being executed in parallel, though the events from parallel test runs are still mixed in the output. But the new code must be cleaned up before fixing that.

Let's Code Jumi #172: Refactoring TestClassRunner (Part 2) MP4
Let's Code Jumi #173: Refactoring TestClassRunner (Part 3) MP4
Let's Code Jumi #174: Refactoring TestClassRunner (Part 4) MP4
Let's Code Jumi #175: Text UI Parsing (Part 1) MP4

To improve the end-to-end tests to detect the incompleteness of the system, I will need to parse the text UI.

Let's Code Jumi #176: Text UI Parsing (Part 2) MP4
Let's Code Jumi #177: Text UI Parsing (Part 3) MP4
Let's Code Jumi #178: Imports (Part 1) MP4

Our code generator tries to import primitive types, so that needs to be fixed before we can add Run IDs to the SuiteListener interface. This is also a chance to leave the code a little bit better than we found it.

Let's Code Jumi #179: Imports (Part 2) MP4
Let's Code Jumi #180: Enter RunId (Part 1) MP4

Introducing Run IDs step by step, to make it possible to identify concurrent test runs.

Let's Code Jumi #181: Enter RunId (Part 2) MP4
Let's Code Jumi #182: Primitive Obsession (Part 1) MP4

Removing primitive obsession by replacing the use of ints with RunId. Tens of places need to be updated, so it's important to proceed in small steps, passing all tests every couple of minutes.

Let's Code Jumi #183: Primitive Obsession (Part 2) MP4
Let's Code Jumi #184: Regular Expressions (Part 1) MP4

Adding support for multiple test runs into TextUIParser. Lots of regular expressions are needed, including less often used regex features such as positive lookahead and embedded flag expressions.

Let's Code Jumi #185: Regular Expressions (Part 2) MP4
Let's Code Jumi #186: Regular Expressions (Part 3) MP4
Let's Code Jumi #187: Regular Expressions (Part 4) MP4

Adding support for multiple test runs into TextUIParser. Lots of regular expressions are needed, including less often used regex features such as positive lookahead and embedded flag expressions.

Let's Code Jumi #188: Checking Test Runs (Part 1) MP4

With TextUIParser implemented, we can improve the end-to-end tests to check individual test runs, which will expose what has not yet been implemented in the support for multiple test runs.

Let's Code Jumi #189: Checking Test Runs (Part 2) MP4
Let's Code Jumi #190: Calm Before the Storm (Part 1) MP4

The next feature to add is generating the RunIds. But before implementing that, let's take a moment to refactor the classes which will soon be modified.

Let's Code Jumi #191: Calm Before the Storm (Part 2) MP4
Let's Code Jumi #192: Calm Before the Storm (Part 3) MP4
Let's Code Jumi #193: Calm Before the Storm (Part 4) MP4
Let's Code Jumi #194: Design Feedback (Part 1) MP4

Writing unit tests in SuiteRunnerTest revealed that the DriverFinder interface makes things hard to test, so let's improve the design to make it testable.

Let's Code Jumi #195: Design Feedback (Part 2) MP4
Let's Code Jumi #196: Fixing Event Stub Conflicts (Part 1) MP4

An earlier refactoring exposed a problem with the code generator which caused the generated event stubs of one interface to overwrite those of another interface.

Let's Code Jumi #197: Fixing Event Stub Conflicts (Part 2) MP4
Let's Code Jumi #198: Fixing Event Stub Conflicts (Part 3) MP4
Let's Code Jumi #199: Fixing Event Stub Conflicts (Part 4) MP4
Let's Code Jumi #200: Generating RunIds (Part 1) MP4

The user interface supports multiple test runs, but the backend does not yet generate unique RunIds for the runs.

Let's Code Jumi #201: Generating RunIds (Part 2) MP4
Let's Code Jumi #202: Generating RunIds (Part 3) MP4
Let's Code Jumi #203: Generating RunIds (Part 4) MP4
Let's Code Jumi #204: Run Events (Part 1) MP4

The RunIds and the onRunStarted/onRunFinished events must still be propagated through the rest of the system and put into full use.

Let's Code Jumi #205: Run Events (Part 2) MP4
Let's Code Jumi #206: Run Events (Part 3) MP4
Let's Code Jumi #207: Run Events (Part 4) MP4
Let's Code Jumi #208: Run Events (Part 5) MP4
Let's Code Jumi #209: Run Events (Part 6) MP4
Let's Code Jumi #210: Isolated Tests MP4

When I rewrote TestClassRunnerTest and SuiteRunnerTest in specification style, I left behind tests which were not isolated - they were checking more things than just the one thing they were interested in. I figured out a way to write them better.

Let's Code Jumi #211: Redundant Parameters (Part 1) MP4

With the onRunStarted event and RunId parameters in place, some of SuiteListener's other parameters can be deduced from the RunId, so they can be removed as redundant.

Let's Code Jumi #212: Redundant Parameters (Part 2) MP4
Let's Code Jumi #213: Redundant Parameters (Part 3) MP4
Let's Code Jumi #214: Misc Refactoring (Part 1) MP4

Some small refactorings. A nice feature in IntelliJ IDEA is "Analyze | Run Inspection by Name" which lets you apply a quickfix with one command for all found problems in the whole project - in this case adding missing @Override annotations.

Let's Code Jumi #215: Misc Refactoring (Part 2) MP4
Let's Code Jumi #216: Demuxing Denormalizer (Part 1) MP4

Extracting from TextUI a bunch of reusable classes for processing suite results.

Let's Code Jumi #217: Demuxing Denormalizer (Part 2) MP4
Let's Code Jumi #218: Demuxing Denormalizer (Part 3) MP4
Let's Code Jumi #219: Misc Refactoring (Part 3) MP4

Still some more small refactorings.

Refactoring - Actors
Let's Code Jumi #220: ActorRef (Part 1) MP4

The Jumi Actors library can be made easier and safer to use by introducing a reference class, a bit like in Akka Actors. This is the first step for a bunch of design improvements to the actors library.

Let's Code Jumi #221: ActorRef (Part 2) MP4
Let's Code Jumi #222: Unified Actors (Part 1) MP4

By unifying the processing of "primary" and "secondary" actors, the internal design can be improved considerably, and later we can get rid of those two different actor categories completely.

Let's Code Jumi #223: Unified Actors (Part 2) MP4
Let's Code Jumi #224: Unified Actors (Part 3) MP4
Let's Code Jumi #225: Decoupled Actor Threads (Part 1) MP4

Creating an actor used to be coupled with creating its thread (or reusing the current thread). By separating those operations we can unify "primary" and "secondary" actors, making the actors much simpler to use.

Let's Code Jumi #226: Decoupled Actor Threads (Part 2) MP4
Let's Code Jumi #227: Decoupled Actor Threads (Part 3) MP4
Let's Code Jumi #228: MonitoredExecutor (Part 1) MP4

If we create an Executor which notifies when it has finished executing its commands, that should help in getting rid of Actors.startUnattendedWorker() and the numerous callbacks of the old WorkerCounter.

Let's Code Jumi #229: MonitoredExecutor (Part 2) MP4
Let's Code Jumi #230: Removing Unattended Workers (Part 1) MP4

Migrating away from using unattended workers into using the new MonitoredExecutor class.

Let's Code Jumi #231: MonitoredExecutor (Part 3) MP4

The MonitoredExecutor class had a bug which was probably the reason why we failed to put it into use.

Let's Code Jumi #232: Removing Unattended Workers (Part 2) MP4

Migrating away from using unattended workers into using the new MonitoredExecutor class.

Let's Code Jumi #233: Removing Unattended Workers (Part 3) MP4
Let's Code Jumi #234: Removing Unattended Workers (Part 4) MP4
Let's Code Jumi #235: Removing Unattended Workers (Part 5) MP4
Let's Code Jumi #236: Terminology Update MP4

After introducing actor threads and removing the unattended workers, the actor tests require some updating.

Let's Code Jumi #237: Eventizer Providers (Part 1) MP4

The usability of the actors library can be improved by making it a single configuration option to support actors of all interface types.

Let's Code Jumi #238: Eventizer Providers (Part 2) MP4
Let's Code Jumi #239: Microbenchmark MP4

Measuring with Caliper whether it makes sense to cache the DynamicEventizer instances.

Let's Code Jumi #240: Thread Naming MP4

Moving thread management and naming from the actor library into an external thread pool and a custom thread factory.

Let's Code Jumi #241: Message Logging (Part 1) MP4

Making debugging actors easier by logging all messages sent to and from actors.

Let's Code Jumi #242: Message Logging (Part 2) MP4
Let's Code Jumi #243: Message Logging (Part 3) MP4
Let's Code Jumi #244: Message Logging (Part 4) MP4
Let's Code Jumi #245: Message Logging (Part 5) MP4
Let's Code Jumi #246: Message Logging (Part 6) MP4
Let's Code Jumi #247: Message Logging (Part 7) MP4
Let's Code Jumi #248: Executor Logging (Part 1) MP4

Some actors delegate work to background threads, so those should also be logged to see the full picture.

Let's Code Jumi #249: Executor Logging (Part 2) MP4
Let's Code Jumi #250: Executor Logging (Part 3) MP4
Let's Code Jumi #251: Stopping Actor Threads (Part 1) MP4

Jumi has not yet needed support for stopping actor threads (it just exits the whole JVM), but for the Jumi Actors library to be general-purpose, there should be a way to release resources.

Let's Code Jumi #252: Stopping Actor Threads (Part 2) MP4
Let's Code Jumi #253: Stopping Actor Threads (Part 3) MP4
Let's Code Jumi #254: Stopping Actor Threads (Part 4) MP4
Let's Code Jumi #255: Failure Handling (Part 1) MP4

Creating hooks for handling uncaught exceptions from actors. Originally only the single-threaded actors had them, but they are also needed in production.

Let's Code Jumi #256: Failure Handling (Part 2) MP4
Let's Code Jumi #257: Failure Handling (Part 3) MP4
Let's Code Jumi #258: Failure Handling (Part 4) MP4
Let's Code Jumi #259: Failure Handling (Part 5) MP4
Let's Code Jumi #260: Failure Handling (Part 6) MP4
Let's Code Jumi #261: Failure Handling (Part 7) MP4
Let's Code Jumi #262: Actor Interface Contracts (Part 1) MP4

Some polish before the Jumi Actors library is ready for being published, for example improved validation of actor interfaces.

Let's Code Jumi #263: Actor Interface Contracts (Part 2) MP4
Let's Code Jumi #264: Custom POM Properties (Part 1) MP4

Maven includes in every JAR a pom.properties file which contains the artifact's groupId, artifactId and version. I would like to include there also Git's revision ID. Unfortunately maven-jar-plugin's pomPropertiesFile option is broken and we need a workaround.

Let's Code Jumi #265: Custom POM Properties (Part 2) MP4
Let's Code Jumi #266: Final Polish MP4

A couple of finishing touches before publishing the actor library. For example fixing a cyclic package dependency revealed by IntelliJ IDEA's Dependency Structure Matrix.

Let's Code Jumi #267: Continuous Delivery MP4

Doing the first release of the Jumi Actors library. I will explain my deployment pipeline for implementing Continuous Delivery to deploy Maven artifacts into Maven Central using Go and Sonatype OSSRH.

You may also read about my deployment pipeline, and how to implement it yourself, in the article Continuous Delivery with Maven and Go into Maven Central.

Bugfix - WorkerCounter
Let's Code Jumi #268: Concurrency Bug (Part 1) MP4

Though it had not yet bitten me, I realized that WorkerCounter has a concurrency bug that could cause two onAllWorkersFinished events being fired. Let's try to find a more reliable design...

Let's Code Jumi #269: Concurrency Bug (Part 2) MP4
Let's Code Jumi #270: Concurrency Bug (Part 3) MP4
Let's Code Jumi #271: Concurrency Bug (Part 4) MP4
Let's Code Jumi #272: More Robust Design (Part 1) MP4

I have one more idea to make WorkerCounter's API harder to use wrong and its implementation simpler.

Let's Code Jumi #273: More Robust Design (Part 2) MP4
Refactoring - Process Lifecycle
Let's Code Jumi #274: Command Line Arguments (Part 1) MP4

Next I will want to get the shutting down of the daemon process from walking skeleton quality to production quality. To get a feel for the code in that area, let's start with something easy - command line parsing.

Let's Code Jumi #275: Command Line Arguments (Part 2) MP4
Let's Code Jumi #276: Command Line Arguments (Part 3) MP4
Let's Code Jumi #277: System Properties (Part 1) MP4

With command line parsing working, next up is passing parameters as system properties.

Let's Code Jumi #278: System Properties (Part 2) MP4
Let's Code Jumi #279: System Properties (Part 3) MP4
Let's Code Jumi #280: Final Decoupling MP4

The recent unit tests failed when doing a clean build because JumiLauncher was still coupled with the embedded daemon JAR.

Let's Code Jumi #281: Process Liveliness (Part 1) MP4

To get started on daemon shutdown commands, we need to expose the java.lang.Process instance to assert whether it's dead or alive.

Let's Code Jumi #282: Process Liveliness (Part 2) MP4
Let's Code Jumi #283: Launcher Actors (Part 1) MP4

The code which sends the startup command to the daemon is from the original walking skeleton and not unit tested, which makes it hard to modify. This part must be re-designed before we can add support for a second command - the shutdown command.

Let's Code Jumi #284: Launcher Actors (Part 2) MP4
Let's Code Jumi #285: Launcher Actors (Part 3) MP4
Let's Code Jumi #286: Launcher Actors (Part 4) MP4
Let's Code Jumi #287: Launcher Actors (Part 5) MP4
Let's Code Jumi #288: Launcher Actors (Part 6) MP4
Let's Code Jumi #289: Launcher Actors (Part 7) MP4
Let's Code Jumi #290: Unit Tests (Part 1) MP4

The formerly monolithic JumiLauncher has now been split into multiple actors, each of which can be more or less unit tested in isolation.

Let's Code Jumi #291: Unit Tests (Part 2) MP4
Let's Code Jumi #292: Unit Tests (Part 3) MP4
Let's Code Jumi #293: Unit Tests (Part 4) MP4
Let's Code Jumi #294: Network Layer (Part 1) MP4

The current network layer is too tightly coupled to the idea that the launcher connects to the daemon. Let's create an anti-corruption layer over Netty.

Let's Code Jumi #295: Network Layer (Part 2) MP4
Let's Code Jumi #296: Network Layer (Part 3) MP4
Let's Code Jumi #297: Network Layer (Part 4) MP4
Let's Code Jumi #298: Network Layer (Part 5) MP4
Let's Code Jumi #299: Network Layer (Part 6) MP4
Let's Code Jumi #300: Unit Tests (Part 5) MP4

The formerly monolithic JumiLauncher has now been split into multiple actors, each of which can be more or less unit tested in isolation.

Let's Code Jumi #301: Unit Tests (Part 6) MP4
Let's Code Jumi #302: Unit Tests (Part 7) MP4
Let's Code Jumi #303: Unit Tests (Part 8) MP4
Let's Code Jumi #304: Daemon Shutdown (Part 1) MP4

With the launcher code made clean, it's possible to start implementing the shutting down of the daemon process.

Let's Code Jumi #305: Daemon Shutdown (Part 2) MP4
Let's Code Jumi #306: Disconnecting MP4

In order to make the daemon exit after the launcher disconnects, we must implement disconnecting network connections and a notification about the disconnection.

Let's Code Jumi #307: Releasing Resources Test (Part 1) MP4

We could test individually that the launcher releases each resource (i.e. threads and sockets) when it is closed, but it would be easy to forget some resource. So let's write a generic test that all resources are released.

Let's Code Jumi #308: Releasing Resources Test (Part 2) MP4
Let's Code Jumi #309: Releasing Resources Test (Part 3) MP4
Let's Code Jumi #310: Stopping Threads (Part 1) MP4

The easiest resource to release is JumiLauncher's actor threads, which also drives us to promote some bootstrap test code into production code.

Let's Code Jumi #311: Stopping Threads (Part 2) MP4
Let's Code Jumi #312: Stopping Threads (Part 3) MP4
Let's Code Jumi #313: Releasing Resources Test (Part 4) MP4

I was able to figure out a way to get a list of all Socket and ServerSocket instances, so it will be possible to write a test that the launcher closes all network connections.

Let's Code Jumi #314: Closing Sockets (Part 1) YouTube MP4

Releasing all resources reserved by the network layer.

Let's Code Jumi #315: Closing Sockets (Part 2) YouTube MP4
Let's Code Jumi #316: Closing Sockets (Part 3) YouTube MP4
Let's Code Jumi #317: Closing Sockets (Part 4) YouTube MP4
Let's Code Jumi #318: Multiple Clients (Part 1) YouTube MP4

Improving the network layer to support multiple clients connecting to the server.

Let's Code Jumi #319: Multiple Clients (Part 2) YouTube MP4
Let's Code Jumi #320: Timeouts (Part 1) YouTube MP4

Testing anything which deals with the current time is hard, because you need to fake the current time or else suffer from flaky and/or slow tests. Encapsulating time and hiding it behind easily testable abstractions is the way to go.

Let's Code Jumi #321: Timeouts (Part 2) YouTube MP4
Let's Code Jumi #322: Timeouts (Part 3) YouTube MP4
Let's Code Jumi #323: Flakiness (Part 1) YouTube MP4

I think I finally found the cause of the flaky network and end-to-end tests; a concurrency issue in what events Netty fires. Also the tests for the timeout class and resource cleanup had issues. Concurrency is hard.

Let's Code Jumi #324: Flakiness (Part 2) YouTube MP4
Let's Code Jumi #325: Flakiness (Part 3) YouTube MP4
Let's Code Jumi #326: Flakiness (Part 4) YouTube MP4
Let's Code Jumi #327: Shutdown Timeouts (Part 1) YouTube MP4

Connecting the dots to shutdown the daemon after a timeout, after the launcher disconnects or doesn't connect in the first place.

Let's Code Jumi #328: Shutdown Timeouts (Part 2) YouTube MP4
Let's Code Jumi #329: Shutdown Timeouts (Part 3) YouTube MP4
Let's Code Jumi #330: Shutdown Timeouts (Part 4) YouTube MP4
Let's Code Jumi #331: Shutdown Timeouts (Part 5) YouTube MP4
Let's Code Jumi #332: Lifecycle Messages (Part 1) YouTube MP4

The daemon process should print its version number on startup and another message on shutdown. That would make reading the logs much easier.

Let's Code Jumi #333: Lifecycle Messages (Part 2) YouTube MP4
Let's Code Jumi #334: Lifecycle Messages (Part 3) YouTube MP4
Let's Code Jumi #335: Suite Configuration (Part 1) YouTube MP4

To avoid changing JumiLauncher always when new suite parameters are added, the current approach needs to be refactored.

Let's Code Jumi #336: Suite Configuration (Part 2) YouTube MP4
Let's Code Jumi #337: Suite Configuration (Part 3) YouTube MP4
Let's Code Jumi #338: Daemon Configuration (Part 1) YouTube MP4

The SuiteConfiguration class is a bit non-cohesive, because it holds also daemon-related parameters which are used differently from suite-related parameters.

Let's Code Jumi #339: Daemon Configuration (Part 2) YouTube MP4
Let's Code Jumi #340: Daemon Configuration (Part 3) YouTube MP4
Let's Code Jumi #341: Unit Tests (Part 1) YouTube MP4

I have a bunch of ideas how to still refactor the daemon and suite configuration classes, but a prerequisite for quick refactoring is good unit test coverage.

Let's Code Jumi #342: Unit Tests (Part 2) YouTube MP4
Let's Code Jumi #343: Phase Change Pattern YouTube MP4

I invented a design pattern which makes it easy to update immutable objects without language support, by providing a way to make an object immutable and back again mutable.

Let's Code Jumi #344: Generic Properties (Part 1) YouTube MP4

Refactoring towards a generic way of representing DaemonConfiguration's bean properties, to convert them to and from system properties.

Let's Code Jumi #345: Generic Properties (Part 2) YouTube MP4
Let's Code Jumi #346: Generic Properties (Part 3) YouTube MP4
Refactoring - Java 7 Migration
Let's Code Jumi #347: Bytecode Assertions (Part 1) YouTube MP4

A too high Java class file version can break its consumers, so it's worth writing a test for. At the same time we can make it easier to write assertions for all class files in a JAR file.

Let's Code Jumi #348: Bytecode Assertions (Part 2) YouTube MP4
Let's Code Jumi #349: Bytecode Assertions (Part 3) YouTube MP4
Let's Code Jumi #350: Java 7 Language Level YouTube MP4

It turns out that changing a project's language level is not as simple as it seems. Changing Maven's settings on a per-module basis is easy, but IntelliJ IDEA 11 doesn't support compiling multiple modules with mixed language levels (IIRC, newer IDEA versions do support it).

Let's Code Jumi #351: NIO.2 Migration (Part 1) YouTube MP4

Java 7 comes with a new file I/O API (NIO.2), which has numerous improvements over java.io.File. Upgrading to the new API is best done in small steps, the same way as when refactoring to remove primitive obsession.

Let's Code Jumi #352: NIO.2 Migration (Part 2) YouTube MP4
Let's Code Jumi #353: NIO.2 Migration (Part 3) YouTube MP4
Let's Code Jumi #354: NIO.2 Migration (Part 4) YouTube MP4