Skip to content
This repository has been archived by the owner on Oct 9, 2019. It is now read-only.

On testing Cmd.batch in update functions: Expect.cmd? #220

Open
thenikso opened this issue Dec 14, 2017 · 5 comments
Open

On testing Cmd.batch in update functions: Expect.cmd? #220

thenikso opened this issue Dec 14, 2017 · 5 comments

Comments

@thenikso
Copy link

thenikso commented Dec 14, 2017

Hi all!

This is more of a question but I am adding a proposal to have it be issue worthy :P

I would like to test an update function so that I am sure that a specific case generates a specific command. The problem is that the command is in a batch.

How would you go about it? Would it make sense to add an Expect.cmd, which would match both a Cmd to Cmd and a Cmd inside a batch?

Thanks!

@drathier
Copy link
Collaborator

It's hard to test against Cmd since it's opaque (we can't read its contents), barely type-safe (the a in Cmd a is discarded) and defined in javascript (magic). I can't think of a way to test the built-in Cmd type. I'm not even sure equality works on it.

You could define your own and use that, or any kind of non-opaque datatype, and test against that. It wouldn't quite match the semantics of Cmd still, unless you use js.

@thenikso
Copy link
Author

Yes, continuing my exploration I also realised that while testing an update command, you always want to test the batch as a whole when you come to it.

So doing an Expect.equal is preferable anyway.

Thanks, feel free to close this if there is no more segue.

@drathier
Copy link
Collaborator

For future reference, what did you end up doing? Can you compare Cmd to see if it was built in the same exact order, or is it order-independent? Sounds like it's at least comparable.

@harrysarson
Copy link

I investigated equality with Cmd's, running the following tests on elm 18

module CmdEqualitySpec exposing (suite)

import Expect
import Test exposing (..)
import Task
import Http

type Msg = TestMsg String | NewBook (Result Http.Error String)

taskCmd =
    Task.perform TestMsg (Task.succeed "a task the succeeds")

taskCmd2 =
    Task.perform TestMsg (Task.succeed "a task the succeeds")
    
httpCmd =
    Http.send NewBook <|
      Http.getString "https://example.com/books/war-and-peace.md"

suite : Test
suite =
    describe "Testing of Cmd's"
        [ test "A command is equal to itself" <|
              \() -> taskCmd
                |> Expect.equal taskCmd
        , test "A command is equal to an identical command"  <|
              \() -> taskCmd
                |> Expect.equal taskCmd2
        , test "Cmd.none is equal to its self"  <|
              \() -> Cmd.none
                |> Expect.equal Cmd.none
        , test "The Cmd.map identity function preserves equality"  <|
              \() -> Cmd.none
                |> Expect.equal (Cmd.map identity Cmd.none)
        , test "A Command is equal to the batched version of itself" <|
              \() -> Cmd.none
                |> List.singleton
                |> Cmd.batch
                |> Expect.equal Cmd.none
        , test "Commands batched in the same order are equal" <|
              \() -> [ taskCmd, httpCmd ]
                |> Cmd.batch
                |> Expect.equal (Cmd.batch [ taskCmd, httpCmd ])
        , test "Commands batched in different orders are equal" <|
              \() -> [ taskCmd, httpCmd ]
                |> Cmd.batch
                |> Expect.equal (Cmd.batch [ httpCmd, taskCmd ])
        ]

gives the following output

elm-test 0.18.12
----------------

Running 8 tests. To reproduce these results, run: elm-test --fuzz 100 --seed 1519579438

↓ CmdEqualitySpec
↓ test of Cmd's
✗ Single Commands are equal to identical commands

    This test failed because it threw an exception: "Error: Trying to use `(==)` on functions. There is no way to know if functions are "the same" in the Elm sense. Read more about this at http://package.elm-lang.org/packages/elm-lang/core/latest/Basics#== which describes why it is this way and what the better version will look like."


↓ CmdEqualitySpec
↓ test of Cmd's
✗ The Cmd.map identity function preserves equality

    { type = "node", branches = [] }
    ╷
    │ Expect.equal
    ╵
    { type = "map", tagger = <function>, tree = { type = "node", branches = [] } }


↓ CmdEqualitySpec
↓ test of Cmd's
✗ Single Commands are equal to the batched version of themselves

    { type = "node", branches = [{ type = "leaf", home = "Task", value = Perform <task> }] }
    ╷
    │ Expect.equal
    ╵
    { type = "leaf", home = "Task", value = Perform <task> }


↓ CmdEqualitySpec
↓ test of Cmd's
✗ Cmd.none is equal to the batched version of its self

    { type = "node", branches = [{ type = "node", branches = [] }] }
    ╷
    │ Expect.equal
    ╵
    { type = "node", branches = [] }


↓ CmdEqualitySpec
↓ test of Cmd's
✗ Batched commands in a different order are equal

    { type = "node", branches = [{ type = "leaf", home = "Task", value = Perform <task> },{ type = "leaf", home = "Task", value = Perform <task> }] }
    ╷
    │ Expect.equal
    ╵
    { type = "node", branches = [{ type = "leaf", home = "Task", value = Perform <task> },{ type = "leaf", home = "Task", value = Perform <task> }] }



TEST RUN FAILED

Duration: 188 ms
Passed:   3
Failed:   5

@harrysarson
Copy link

So Cmds are comparable however:

  • Comparing two different commands that should be indentical throws an error.
  • Cmd.map always creates a different Cmd even if called with identity.
  • Batched commands are only equal if they are created in exactly the same order.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants