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.
- Project website: http://jumi.fi
- Project repo: https://github.com/luontola/jumi
- 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 |
||
| 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 |
||
| 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 |
||
| 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 |
||
| 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 |
||
| 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 |
||
| 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 |
||
| 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 |
||
| 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 |
||
| 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 |
||
| 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 |
||
| Let's Code Jumi #211: Redundant Parameters (Part 1) | MP4 | |
With the |
||
| 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 |
||
| Let's Code Jumi #215: Misc Refactoring (Part 2) | MP4 | |
| Let's Code Jumi #216: Demuxing Denormalizer (Part 1) | MP4 | |
Extracting from |
||
| 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 |
||
| 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 |
||
| Let's Code Jumi #231: MonitoredExecutor (Part 3) | MP4 | |
The |
||
| Let's Code Jumi #232: Removing Unattended Workers (Part 2) | MP4 | |
Migrating away from using unattended workers into using the new |
||
| 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 |
||
| 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 |
||
| 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 |
||
| 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 |
||
| Let's Code Jumi #281: Process Liveliness (Part 1) | MP4 | |
To get started on daemon shutdown commands, we need to expose the |
||
| 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 |
||
| 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 |
||
| 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 |
||
| 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 |
||
| 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 |
||
| 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 |
||
| 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 |
||
| 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 | |