The Journal: comparing runs

Comparing finds what separates the runs that fail from the ones that pass, without reading any one run's story first. This lesson records all four of Orders' scenarios, then compares the one that fails with one that passes. Read Orders.ek9 first. To play it in the IDE: Help > Lessons > Debugging and the Journal…, or ek9 -ide -lesson journal-comparing.

The EK9 IDE as the lesson opens

Start from

The code the lesson starts from: copy it into a file of your own and follow the steps.

Orders.ek9

#!ek9
<?-
  debug-journal / orders: a defect that shows itself late.

  An order's total goes negative only when a refund FOLLOWS a discount: the refund is taken from what is left to pay
  (the discounted total) rather than from what was paid. Nothing fails at the refund; the invoice, later, refuses a
  negative total with a Panic. Scenario: 1 add, 2 +discount, 3 +discount +refund (fails), 4 +refund (passes).
-?>
defines module live.orders

  defines constant
    NOTHING <- 0
    PERCENT <- 100
    PRICE <- 100
    HALF <- 50
    REFUNDED <- 80
    DISCOUNTS <- 2
    REFUNDS <- 3

  defines class

    Order
      total as Integer: 0

      add()
        -> amount as Integer
        total += amount

      discount()
        -> percent as Integer
        saving <- total * percent / PERCENT
        total -= saving

      invoice()
        <- rtn as String?
        require total >= NOTHING
        rtn: `invoice for ${total}`

      refund()
        -> amount as Integer
        total -= amount

      default operator ?

  defines program

    Orders()
      -> scenario as Integer
      stdout <- Stdout()
      order <- Order()
      order.add(PRICE)
      if scenario == DISCOUNTS or scenario == REFUNDS
        order.discount(HALF)
      if scenario >= REFUNDS
        order.refund(REFUNDED)
      stdout.println(order.invoice())

//EOF

dev/orders_tests.ek9

#!ek9
<?-
  debug-journal / orders: the tests, for trying coverage in the IDE (-t, the coverage toggle Alt+Cmd+F6).

  They cover adding, a discount alone and a refund alone - each passes. The defect path (a refund AFTER a discount,
  which the invoice refuses with a Panic) and the Orders program itself are deliberately left untested, so coverage
  shows what the tests do not reach.
-?>
defines module live.orders.tests

  references
    live.orders::HALF
    live.orders::Order
    live.orders::PRICE
    live.orders::REFUNDED

  defines constant
    FULL_PRICE <- "invoice for 100"
    HALF_PRICE <- "invoice for 50"
    PRICE_LESS_REFUND <- "invoice for 20"

  defines program

    @Test
    AddOnly()
      order <- Order()
      order.add(PRICE)
      assert order.invoice() == FULL_PRICE

    @Test
    HalfDiscount()
      order <- Order()
      order.add(PRICE)
      order.discount(HALF)
      assert order.invoice() == HALF_PRICE

    @Test
    RefundWithoutDiscount()
      order <- Order()
      order.add(PRICE)
      order.refund(REFUNDED)
      assert order.invoice() == PRICE_LESS_REFUND

//EOF

Step 1: A program with passing and failing runs

Orders runs scenario 1, 2, 3 or 4: an add, then (scenario 2 or 3) a discount, then (scenario 3 or 4) a refund. Scenario 3 - discount, then refund - is the only one that fails: the refund is taken from the discounted total, and the invoice refuses the negative result.

The EK9 IDE once this is done: Orders runs scenario 1, 2, 3 or 4

Step 2: Record several runs

Choose Run > New Journal Investigation…

The EK9 IDE once this is done: Choose Run > New Journal Investigation…

Watch Order.total, and give all four scenarios - one input set per line: 1, 2, 3, 4. Choose Start.

The EK9 IDE just before choosing Start: Watch Order.total, and give all four scenarios - one input set per line

The program runs four times, once per scenario, while the Journal records every change to Order.total. Three pass; scenario 3 fails - and all four show in the Journal tab, already selected and compared.

The EK9 IDE once this is done: The program runs four times, once per scenario, while the Journal records every change to Order.total

Step 3: Choose two to compare

Click the FAIL run (scenario 3) to select it alone, then ⌘-click the pass run for scenario 1: now exactly those two are selected, and compared - not all four.

The EK9 IDE once this is done: Click the FAIL run (scenario 3) to select it alone, then ⌘-click the pass run for scenario 1

Step 4: What only the failing run did

The side by side lines up the failing run against the passing one, step by step. "not in this run" under pass, for the discount and the refund, is what only the failing run did - read from the top: the add is the same in both, then the failing run alone discounts and refunds.

The EK9 IDE once this is done: The side by side lines up the failing run against the passing one, step by step

Step 5: The Journal Report

Choose Report…

The EK9 IDE once this is done: Choose Report…

Say what you think is wrong - citing the step and line that show it - and choose Write Report. It opens as a page: what was run, how each run ended, and the two side by side - with report.json beside it for a model to read.

The EK9 IDE just before choosing Write Report: Say what you think is wrong - citing the step and line that show it - and choose Write Report

The result

That is comparing: choose the runs, read what separates them, and hand the report to someone who has not seen the IDE. Trying a variation of one run - without filling the whole dialog again - is the next lesson.

The EK9 IDE when the lesson has finished

Where this lesson comes from