TDD in Eventide: You just instantiate things

On Saturday we started the TDD flow in an Eventide component, and we had all of the excitement of… laying out the folder structure. I’m not sure how far we’ll get today. I’ll write what seems like 2 minutes of reading, and then we’ll pick it up again tomorrow.

Here’s a refresher link to the repo, and we’re in the test/automated/handle_commands/build/initiated.rb file. First, we need access to test/automated/automated_init.rb, and then we’ll set up the basic structure of the test. We’re using TestBench to write these tests, and diving deep into it will have to wait for another email. It provides us context blocks, and you’ll see how those blocks nest within one another in the output:

require_relative "../../automated_init"

context "Handle commands" do
  context "Build" do
    context "Initiated" do
    end
  end
end

TestBench test files are Just Ruby Programs™, so you can run them like you would any other Ruby program with ruby test/automated/handle_commands/build/initiated.rb:

ruby 3.2.1 (2023-02-08 revision 31819e82c8) [arm64-darwin21]

TEST_BENCH_DETAIL: nil

Handle Commands
  Build
    Initiated

Our context names match the folder structure within test/automated, and this is useful for understanding where a test is located. Having run the test at this point, we’ve verified that we’ve setup our contexts correctly, and that we’ve found our link to the rest of the project (automated_init.rb) correctly.

Now then, let’s write a test.

This sparks joy

Here is one of my favorite things about Eventide. We’re going to write a test for a message handler class. The class in question is going to live at lib/composite_component/handlers/commands.rb. Handlers in Eventide components are analogous to controllers in an MVC framework. Unlike in an MVC framework, watch this (omitting some of the lines for space):

context "Initiated" do
  handler = Handlers::Commands.new
end

Did you catch it? We just instantiate an instance of the handler class and then call methods on it. If you find you have too much peace and goodwill towards mankind in your heart, try doing that with a controller in the predominant web framework in Ruby, and you’ll be cured of that in a jiffy.

Let’s try running the test again:

> ruby test/automated/handle_commands/build/initiated.rb

TEST_BENCH_DETAIL: nil

Handle Commands
  Build
    Initiated
      test/automated/handle_commands/build/initiated.rb:6:in `block (3 levels) in <main>': uninitialized constant Handlers (NameError)

# A bunch more stack trace

The test is telling us that we don’t have something called Handlersin our project yet. Thats fine. We can add it at lib/composite_component/handlers/commands.rb:

module CompositeComponent
  module Handlers
    class Commands
    end
  end
end

We’re within the CompositeComponent and then we add a module and class named Handlers and Commands, respectively. We don’t have to name them that, but that’s the convention. This is the class that handles commands belonging to the composite-component.

One last step, we need to add this to our component loader file which in our case you’ll find at lib/composite_component.rb. It’s a sibling to the composite_component folder that all our component code is in. We don’t do auto-loaders in Eventide because we don’t hate ourselves, so each time you add a file to the project, you’ll add a line in here. Order matters somewhat, so be sure to reference the completed file in the repo to see how to order unfolds. I don’t want to put that much duplication in our emails.

Anyway, the line we’re adding is:

require "composite_component/handlers/commands" 

When we require automated_init.rbinto our program at the top of the test file, we follow a chain that leads to the load_path.rb file in the root of the repository. This sets it up so that when we require a file, it looks for it off of lib.

One of the tenets of TDD is that we write enough code to get our failing test to pass. Let’s see how we did:

$ ruby test/automated/handle_commands/build/initiated.rb
ruby 3.2.1 (2023-02-08 revision 31819e82c8) [arm64-darwin21]

TEST_BENCH_DETAIL: nil

Handle Commands
  Build
    Initiated

We’re back to a passing state.

This email is getting long now, so let’s just recap what we learned:

  1. How to set up a test in TestBench
  2. When we test things in Eventide, we just instantiate them and call methods on them
  3. Some of the other file structure in an Eventide component

Tomorrow, or next time the email is about TDD, we’ll get into the notion of test controls, one of my favorite things I’ve learned about since using Eventide, although the concept is not Eventide-specific.


Like this message? I send out a short email each day to help software development leaders build organizations the deliver value. Join us!


Get the book!

Ready to learn how to build an autonomous, event-sourced microservices-based system? Practical Microservices is the hands-on guidance you've been looking for.

Roll up your sleeves and get ready to build Video Tutorials, the next-gen web-based learning platform. You'll build it as a collection of loosely-coupled autonomous services, developing a message store interface along the way.

When you're done, you'll be ready to contribute to microservices-based projects.

In ebook or in print.