A software designer website

Abaks: testing core domain

Gautier DI FOLCO June 14, 2023 [dev] #haskell #design #project #abaks

Previous log saw the introduction of Commands.

One of the reason I favor Clean Architecture specifically over Hexagonal Architecture is to have a pure core domain, easily testable (without mocks or specific interpreters).

I also chose to build tested Command's Event's relying on previous Commands to avoid testing impossible states.

Note that the lack of legacy is also a strong motivation.

We can start with a simple helper which apply Commands one after the other, keeping results and accumulating Events:

applyCommands ::
  [CommandHandler AbaksEvent ExplainedError] ->
  [Either ExplainedError (Events AbaksEvent)]
applyCommands = snd . foldl' go (mempty, mempty)
    go (events, previousResults) handler =
      let result = applyCommand handler events
       in (either (const events) (events <>) result, previousResults <> [result])

Then we can start to write some tests:

spec :: Spec
spec = do
  describe "Entities" $ do
    it "startPeriod should work" $
      applyCommands [startPeriod anyPeriodId periodName periodStart periodEnd (Amount 0)]
        `shouldSatisfy` liftEq ($) [isRight]
    it "deleteEntry should fail" $
      applyCommands [deleteEntry (EntryId 42) "do not exist"]
        `shouldSatisfy` liftEq ($) [isLeft]