Giter Site home page Giter Site logo

elm-explorations / test Goto Github PK

View Code? Open in Web Editor NEW
234.0 234.0 40.0 1.16 MB

Write unit and fuzz tests for Elm code.

Home Page: https://package.elm-lang.org/packages/elm-explorations/test/latest

License: BSD 3-Clause "New" or "Revised" License

Elm 99.04% JavaScript 0.45% Shell 0.51%

test's People

Contributors

avh4 avatar bastes avatar bobwhitelock avatar deadfoxygrandpa avatar drathier avatar eeue56 avatar fredcy avatar gampleman avatar harrysarson avatar jaapz avatar janiczek avatar jmedding avatar jwoudenberg avatar lydell avatar magopian avatar marc136 avatar maxsnew avatar mbaechler avatar mgold avatar mikem avatar mpizenberg avatar pete-a avatar razzeee avatar rl-king avatar robertjlooby avatar rtoal avatar ursi avatar xdissent avatar yourfin avatar zkessin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

test's Issues

Cannot use Fuzz.custom since Shrink module is not exposed

Currently it appears to be impossible to use Fuzz.custom, since it requires providing a Shrinker but the only way to do that is to create one using the functions in the non-exposed Shrink module.

Related: the documentation for Fuzz.custom refers to:

  • elm-lang/random: should be elm/random, and "which is not core's Random module but has a compatible interface" should be removed
  • eeue56/elm-shrink, which does not exist

Infinite recursion shrinking with fuzz2

Minimal reproduction:

import Expect
import Fuzz
import Test exposing (..)

testRepro : Test    
testRepro =    
    fuzz2 Fuzz.int (Fuzz.constant ()) "reproduce infinite recursion" <|    
        \i j -> Expect.equal True False    

We need to use fuzz2, we need a failing test, and using two constant fuzzers does not reproduce. It does not reproduce if the order of the fuzzers is switched.

Output:

โœ— reproduce infinite recursion

    This test failed because it threw an exception: "RangeError: Maximum call stack size exceeded"

I don't know how long this issue has existed.

Hash fuzzed input to detect duplicates?

When generating random values from a fuzzer, there is no guarantee that each one will be unique. You may ask for 100 cases but get less. It may be possible you get much less.

One solution is to hash each input, store the hashes, and reject inputs with a duplicate hash. We'd need to fail the test after some number of failed attempts to create distinct inputs, perhaps max 20 (2*numberOfRequestedRuns).

Since we'd want a designated union type tag for this failure condition, it makes sense to do this while we're doing a major revision.

Is there any interest in exploring this idea?

Rename Shrinker -> Simplifier?

Hi,

May I give a suggestion: rename the Shrinker type to Simplifier.

This is a suggestion that occurred to me whilst reading through #33 but I thought it worth making a new issue rather than derailing that one.

Following the (de-facto?) principle of using descriptive names in elm, I thought that the meaning of "shrinking a test input" would have been much clearer to me if it had instead been called "simplifying a test input".

From @mgold's comment: #33 (comment)

Let's say I have a test that claims every integer is even. You'll get around 50 failing tests, each with a different odd number. The goal of the shrinker is to tell you that 1 is the "smallest" or "simplest" counterexample to your claim. 1 is "larger" "smaller" than -1, somewhat by convention.

Feel free to close if such a change is not appropriate, or if github is not the appropriate place to make such a suggestion.

Cheers ๐Ÿ‘

API fatal error handler returned after process out of memory

(Sorry if this isn't the right repository, I'm a little at a loss here...)

I have a set of tests in a private project that fails to run. I'm relatively certain that the failure does not represent a bug in the test or the code (i.e. I don't think it's rtfeldman/node-test-runner#290). I haven't tried boiling things down to an SSCCE yet, but will try next. (I wanted to make sure I didn't lose the stack traces.) Here are the error messages I've gotten:

> elm-test

elm-test 0.19.0-rev5
--------------------

Running 14 tests. To reproduce these results, run: elm-test --fuzz 100 --seed 396170984152586 [...]


#
# Fatal error in , line 0
# API fatal error handler returned after process out of memory
#

and

> elm-test

elm-test 0.19.0-rev5
--------------------

Running 14 tests. To reproduce these results, run: elm-test --fuzz 100 --seed 215354435481898 [...]


<--- Last few GCs --->

[17089:0x380a230]   141745 ms: Mark-sweep 1408.2 (1460.8) -> 1408.2 (1444.8) MB, 3321.9 / 0.0 ms  (+ 0.0 ms in 0 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 3322 ms) last resort 
[17089:0x380a230]   145181 ms: Mark-sweep 1408.2 (1444.8) -> 1408.2 (1444.8) MB, 3435.9 / 0.0 ms  last resort 


<--- JS stacktrace --->

==== JS stack trace =========================================

Security context: 0x219007da8799 <JSObject>
    1: /* anonymous */ [/home/ethan/src/quartermaster/frontend/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:~10389] [pc=0x467f709e9e1](this=0xd99f2d746f1 <JSFunction (sfi = 0x13127ca2071)>,hour=10,minute=26,second=23)
    2: /* anonymous */(aka /* anonymous */) [/home/ethan/src/quartermaster/frontend/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:~10416] [pc=0...

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
 1: node::Abort() [/home/ethan/.nvm/versions/node/v8.5.0/bin/node]
 2: 0x13576dc [/home/ethan/.nvm/versions/node/v8.5.0/bin/node]
 3: v8::Utils::ReportOOMFailure(char const*, bool) [/home/ethan/.nvm/versions/node/v8.5.0/bin/node]
 4: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [/home/ethan/.nvm/versions/node/v8.5.0/bin/node]
 5: v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationSpace) [/home/ethan/.nvm/versions/node/v8.5.0/bin/node]
 6: v8::internal::Runtime_AllocateInTargetSpace(int, v8::internal::Object**, v8::internal::Isolate*) [/home/ethan/.nvm/versions/node/v8.5.0/bin/node]
 7: 0x467f6f046fd

After either message, elm-test hangs (doesn't finish in 6-7 minutes) and I have to kill it with Ctrl-C.

Rerunning the tests with the same seed causes the same message, but rerunning the tests with a new seed can produce either message or even succeed after a very long time (~3 min vs. the usual ~15 seconds).

Although the message is about OOMing, my computer still has plenty of free RAM (~2GB according to top). I'm guessing node is exhausting some pre-allocated heap, but I couldn't figure out how to enlarge that heap (unlike e.g. #22 (comment)).

I suspect there's something about my tests and/or fuzzers that consume an awful lot of memory but I haven't figured out exactly what it is. When I try to disable certain parts of my fuzzers I can circumvent the error. In particular, I have had a lot of success converting Fuzz.list a into Fuzz.map (\elem -> [elem]) a. Of course this limits the utility of the test.

Invalid Package Dependencies when using elm/file

There seems to be a version conflict with elm-test and elm/file, to reproduce:

  • mkdir elm-test-bug
  • cd elm-test-bug
  • elm init
  • elm-test init
  • elm-test; this works
  • elm install elm/file
  • elm-test fails because somehow the dependencies are not compatible

Additionally, adding elm-explorations/test as a dependency works just fine, so it looks like the problem is in elm-test itself.

Shrinkers: how do they work?

shrinkers-how-do-they-work

So, I've been trying to use the Fuzz.custom function to work around the disappearance of Fuzz.conditional and Fuzz.andThen on a pre-existing codebase that I'm trying to migrate ; and I saw that I needed a Random.Generator(good, I know what they do is generate stuff randomly in a functionally pure way, and can work on one of those with Random.andThen and Random.mapand other niceties) and a Shrink.Shrinker.

Ok, let's read the docs on this last one... those excerpts from the doc seem relevant:

If the fuzzer can make your test fail, it also knows how to "shrink" that failing input into more minimal examples, some of which might also cause the tests to fail.

Well, looks like it's a thing that does something called "shrinking" on a failing sample. Shrinking sounds like it's making things smaller. And this "shrunk" sample should attempt to make the sample fail. So far, so good.

type alias Shrinker a =
    a -> LazyList a

The shrinker type. A shrinker is a function that takes a value and returns a list of values that are in some sense "smaller" than the given value. If there are no such values conceptually, then the shrinker should just return the empty list.

So, it's an alias for a function that takes a value and returns a fancy list of values, not just one, and they need to be "smaller". What does "smaller" means in this context? Like, 0 is smaller than 1? -1 is smaller than 0? "" is smaller than "a"? Is "Z" smaller than "z"? Is "aa" smaller than "z"?...
Also, why is the word "conceptually" in this sentence?

Oh, there's another function that may make this make more sense:

shrink : (a -> Bool) -> Shrinker a -> a -> a

Perform shrinking. Takes a predicate that returns True if you want shrinking to continue (e.g. the test failed). Also takes a shrinker and a value to shrink. It returns the shrunken value, or the input value if no shrunken values that satisfy the predicate are found.

Still not sure what shrinking really is, but let's read on... Why would I want shrinking to continue, or stop? This predicate doesn't take the test as an input, why would "the test failed" be an example? Should I pass a predicate that internally reference my test itself? It returns the shrunken value. Why only one? I thought shrinkers could return multiple shrunken values? Which one will be selected?

Ok, that didn't help much. Let's see what's next. Oh, a list of shrinker constructors for many types... ok, I could use some of them if I was sure they did what I want. But I don't know what I want yet. Let's see what's next...

convert : (a -> b) -> (b -> a) -> Shrinker a -> b -> LazyList b
Convert a Shrinker of a's into a Shrinker of b's using two inverse functions. ) [...]

Ok, I see the Shrinker a ; where is the Shrinker b? Oh, right, it's the b -> LazyList b that's synonymous at the end of the signature...

Then I see:

[...] If you use this function as follows:

shrinkerB =
    f g shrinkerA
Make sure that

`f(g(x)) == x` for all x
Or else this process will generate garbage.

Wait... what? What is f? What is g? Why would I use f g shrinkerA? Where does it have to do with convert? It will generate garbage unless f(g(x)) == x for all x? I thought f was a function that took two arguments (g and shrinkerA) so why does it takes only one in the f(g(x)) == x law? Is x a function too?

I'll stop here, I guess you understand my point: this is confusing for someone who doesn't already know what shrinkers are, what they're meant to do, and why we need them to work with the Generators to make Fuzzers. And this is kinda important for someone who wants to make their own Fuzzers to understand them, especially when functions like Fuzz.andThen and Fuzz.conditional are deprecated.

Since I'd rather help than give someone else work, I'd love to write a documentation that takes the user by the hand when they try to wrap their head around the subject, but I'd have to understand what Shrinkers are, what they do and why first (and right now, it's still quite fuzzy for me :p).

So, if someone in this fine team would like to take a moment and help me get the basics on Fuzzers so I can send a documentation PR, I'd be happy to do just that in return ;)

Maximum call stack size exceeded when comparing long strings

This might be the same problem as #22 or rtfeldman/node-test-runner#290 but here with very simple data which seems to point to a problem with output string diffing.

So, the following:

sscce : Test
sscce =
    test "Different long strings" <|
        \_ ->
            String.repeat 1000 "a"
                |> Expect.equal (String.repeat 1000 "b")

causes

Tests.elm changed. Rebuilding!

elm-test 0.19.0-beta12
----------------------

Running 1 test. To reproduce these results, run: elm-test --fuzz 100 --seed 354267269012927 /home/nonpop/projects/elm/sscce/tests/Tests.elm

/home/nonpop/projects/elm/sscce/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:579
function _Utils_eqHelp(x, y, depth, stack)
                      ^

RangeError: Maximum call stack size exceeded
    at _Utils_eqHelp (/home/nonpop/projects/elm/sscce/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:579:23)
    at _Utils_eq (/home/nonpop/projects/elm/sscce/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:570:35)
    at /home/nonpop/projects/elm/sscce/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:3452:9
    at Function.f (/home/nonpop/projects/elm/sscce/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:3493:5)
    at A5 (/home/nonpop/projects/elm/sscce/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:113:28)
    at /home/nonpop/projects/elm/sscce/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:3497:13
    at Function.f (/home/nonpop/projects/elm/sscce/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:3434:11)
    at A2 (/home/nonpop/projects/elm/sscce/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:104:28)
    at Function.f (/home/nonpop/projects/elm/sscce/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:3494:11)
    at A5 (/home/nonpop/projects/elm/sscce/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:113:28)

Everything works if I make the strings the same by just changing "b" to "a".

Add the ability to query for keyed nodes

In some cases having keyed html nodes makes a functional difference, so we want to test for it.

I'd like to write something like

          test "Keyed Button has the expected key" <|
            \_ ->
                Html.Keyed.node "button" [] [ ( "key1", Html.text "I'm a button!" ) ]
                    |> Query.fromHtml
                    |> Query.has [ Selector.key "key1" ]

Add the ability to customize the path of test files through elm.json

There's already #34 which is about running tests that live in a non-standard directory. Fortunately, this can now be easily done through elm-test path/to/that/dir.

I believe that ultimately there should be a way to specify the custom paths for tests in a config file. If elm-test allows you to run tests that are not in <root_dir>/tests, then I think it should also allow for specifying that custom paths in elm.json so that 3rd party tools can support that use case as well.

Let me explain my specific scenario: @altaurog added support for 0.19 in ale (a vim plugin) in dense-analysis/ale#2176 (thanks for that!) which corresponds to the issue #64. The code assumes that tests are at <root_dir>/tests. We have a Rails app with frontend in Elm and the Elm tests live in app/javascript/tests, so that fix doesn't work for me in that project.

In our scenario we can freely move those Elm tests to <root_dir>/tests, but I imagine that in the future someone won't have this luxury.


This is just the first thing that came to my mind, perhaps there are other ways to solve this problem and I'm open to hear them!

How to make "negative" fuzzers?

Hi,

I'm trying to migrate a library on Elm 0.19.0 and my tests were relying on Fuzz.conditional to tests cases where an input was "anything but" specific values (ie: I want any integer that is not a multiple of 3 ; I want any string that does not contain some substrings).

I used to do it like this:

Fuzz.conditional
  { retries = 10
  , fallback = always 1
  , condition = \n -> (n |> modBy 3) == 0
  }
  int

Can I do this now? If so, how can I do this now? If not, am I the only one to use that kind of strategy? If so, how do you use fuzzy testing to test those kinds of cases?

Support list shuffling fuzzer

I have a working version of sortedList : List a -> Fuzz (List a) that generates versions of a list with different sort ordering; however, it depends on Random.List.shuffle from elm-community/random-extra:

shuffle : List a -> Fuzzer (List a)
shuffle list =
    Fuzz.custom (Random.List.shuffle list) Shrink.noShrink

I think it's pretty useful to be able to fuzz test that different sort orderings of a list produce the same outcome, so I'd love to have first class support for it.

Installation guide in Readme seems wrong?

With a fresh project under elm 0.19...

npm install -g elm-test command installs elm-test 0.18.13-beta. https://www.npmjs.com/package/elm-test

When I run elm-test init I get the following error:

Created /home/cbass/Projects/projelm/tests
Created /home/cbass/Projects/projelm/tests/elm-package.json
Created /home/cbass/Projects/projelm/tests/Example.elm
/home/cbass/Projects/projelm/.gitignore already exists
/bin/sh: elm-package: command not found
Unhandled exception while running the tests: { Error: Command failed: elm-package install --yes
    at checkExecSyncError (child_process.js:611:11)
    at Object.execSync (child_process.js:648:13)
    at runElmTest (/home/cbass/.nvm/versions/node/v10.10.0/lib/node_modules/elm-test/lib/elm-test.js:291:19)
    at Object.<anonymous> (/home/cbass/.nvm/versions/node/v10.10.0/lib/node_modules/elm-test/lib/elm-test.js:742:1)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Module.require (internal/modules/cjs/loader.js:637:17)
  status: 127,
  signal: null,
  output: [ null, null, null ],
  pid: 4881,
  stdout: null,
  stderr: null }

Kinda confused?

Also started a thread here (https://elmlang.slack.com/archives/C192T0Q1E/p1537193358000100) but not sure if right place for this

Fails on Alpine Linux

When running elm-test on my CI running alpine Linux it fails like so:

$ elm-test
events.js:183
      throw er; // Unhandled 'error' event
      ^

Error: spawn /opt/app/waive/assets/node_modules/elmi-to-json/unpacked_bin/elmi-to-json ENOENT
    at _errnoException (util.js:992:11)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:190:19)
    at onErrorNT (internal/child_process.js:372:16)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    at process._tickCallback (internal/process/next_tick.js:180:9)
    at Function.Module.runMain (module.js:695:11)
    at startup (bootstrap_node.js:191:16)
    at bootstrap_node.js:612:3

Exited with code 1

I connect and check that file it does exist and has the right permissions, but attempting to run it results in bash: /opt/app/waive/assets/node_modules/elmi-to-json/unpacked_bin/elmi-to-json: No such file or directory.

I believe this is due to Alpine Linux's use of musl over libc. The elmi-to-json binary is not statically linked and assumes that libc is present, so it cannot be run.

It's common to use Alpine Linux when using Docker as it currently provides the smallest images available, so it would be beneficial for elm-test to work on this distribution.

Simplify.lazylist cannot be used

https://package.elm-lang.org/packages/elm-explorations/test/latest/Shrink#lazylist

The function Simplify.lazylist has this type signature (note it takes a LazyList as an argument):

lazylist : Shrinker a -> LazyList a -> LazyList (LazyList a)

However, LazyList is not exposed by this package so there is no way that a user can get their hands on a LazyList to pass to Simplify.lazylist. Therefore, (unless I am wrong - entirely possible) there is no way to call this function.

Either:

  • Expose LazyList
  • Remove this function.

Refs: #66
cc: @tmohme

elm-test init creates old folder structure

Just trying to get this working over v19.

I noticed that even though:

  • I have the v19 Elm binary installed for OS X
  • I'm running Elm 19
  • I've got an elm.json at the root of my project

screen shot 2018-09-18 at 6 26 50 pm

Problem: When I run elm-test init it creates a test directory but in that directory I only see:

elm-package.json (why isn't it elm.json ??????)
Example.elm

For troubleshooting, ran npm install -g elm-test again and it appears to have installed the new elm-test for v19 as you can see at the bottom...although I don't know if the prior lines in the install results there are "normal":

screen shot 2018-09-18 at 6 22 30 pm

However after running elm-test init, something isn't right here.

Created /Users/daveschinkel/Code/katas/minMax/elm-minmax-kata/tests
Created /Users/daveschinkel/Code/katas/minMax/elm-minmax-kata/tests/elm-package.json
Created /Users/daveschinkel/Code/katas/minMax/elm-minmax-kata/tests/Example.elm
/Users/daveschinkel/Code/katas/minMax/elm-minmax-kata/.gitignore already exists
/bin/sh: elm-package: command not found
Unhandled exception while running the tests: { Error: Command failed: elm-package install --yes
    at checkExecSyncError (child_process.js:603:11)
    at Object.execSync (child_process.js:640:13)
    at runElmTest (/usr/local/lib/node_modules/elm-test/lib/elm-test.js:291:19)
    at Object.<anonymous> (/usr/local/lib/node_modules/elm-test/lib/elm-test.js:742:1)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Module.require (internal/modules/cjs/loader.js:637:17)
  status: 127,
  signal: null,
  output: [ null, null, null ],
  pid: 14555,
  stdout: null,
  stderr: null }

That creates a test folder but with an elm-package.json in it, not elm.json.

Re-add Test.fuzz4, Test.fuzz5?

When updating some of my tests to use this package, I ran into a few places where I was using Test.fuzz4. My initial solution was to use Fuzz.map4 to map the four arguments into a record, and rewrite my expectation function to take a single record argument, but this seemed pretty messy (introduced some pretty meaningless record types). I ended up writing my own module to replicate Test.fuzz4:

module Test.FuzzN exposing (fuzz4)

import Expect exposing (Expectation)
import Fuzz exposing (Fuzzer)
import Test exposing (Test)


type alias Arguments4 a b c d =
    { argument1 : a
    , argument2 : b
    , argument3 : c
    , argument4 : d
    }


fuzz4 : Fuzzer a -> Fuzzer b -> Fuzzer c -> Fuzzer d -> String -> (a -> b -> c -> d -> Expectation) -> Test
fuzz4 fuzzer1 fuzzer2 fuzzer3 fuzzer4 description expectation =
    Test.fuzz
        (Fuzz.map4 Arguments4 fuzzer1 fuzzer2 fuzzer3 fuzzer4)
        description
        (\{ argument1, argument2, argument3, argument4 } ->
            expectation argument1 argument2 argument3 argument4
        )

(The actual module also implements fuzz5 for completeness.) I realize that Test.fuzz4 and Test.fuzz5 can no longer be described as alternatives to Fuzz.tuple4 and Fuzz.tuple5, so the documentation wording would need to be updated, but I think it makes sense to continue to support them (just like Fuzz.map4 and Fuzz.map5 are still supported).

Thoughts? Would a pull request be welcome? If so, is the above implementation a good one? (Wasn't sure if it might cause issues for shrinking or error message generation, for example...)

Test Cmd

As hinted at on Discourse, there was a plan to add Cmd testing to elm-test.

While there are ways to test effects right now, they involve a lot of boilerplate and indirection, and it seems most appropriate to be able to compare Cmds directly, when it comes to tests.

I opened this issue mainly to track the status of this idea. Is there a concrete plan for this?

How do I make my own Shrinkers?

The documentation in Shrink.elm v1.2.0 says about this topic

Shrinkers have to return a LazyList

. . . but unfortunately with corresponding types (or helper functions) are not exposed, making it for some cases hard to write a Shrinker.
While many custom shrinkers can be easily composed by using the provided shrinkers and helper functions, this is not the case for ADTs (like type abc = A | B | C) - at least I haven't found a way to do this.

My current use case is very similar to creating a shrinker for Maybe - just for a custom type.

Please expose appropriate functions to achieve this and/or adjust the documentation to more elaborately explain creating custom shrinkers.

Edit:
I finally achieved my goals by composing Fuzzers (instead of Shrinkers - in so far it was my fault).
Nevertheless, the documentation for this topic seems misleading (since elm 0.19) as the given advice can't be followed because the mentioned type LazyList is no longer exposed.

Incorporate elm-html-test

For several reasons...

  • Many people seem unaware http://package.elm-lang.org/packages/eeue56/elm-html-test/latest is available (which is a shame - it rocks!)
  • There's no more native whitelist, so it can't be re-published in 0.19 as-is
  • This project is going to have more dependencies on other packages when it gets into testing Cmd values anyway

...the plan is to add elm-html-test here.

This will entail the usual 0.19 changes, plus Native -> Kernel, and updating the README and other docs.

Idea: Better `Char` and `String` Fuzzers

As mentioned in #89, I'm a fan of hedgehog.

hedgehog comes with a useful set of generators for characters and for strings too, such as (as would be written in Elm):

  • lower : Fuzzer Char
  • alphaNum: Fuzzer Char

These are great building blocks for larger fuzzers, as the generator for strings has the form (ignoring Range, discussed separately in #89):

string : Fuzzer Char -> Fuzzer String

Thus allowing the user to choose what class of characters to use when generating a list string.
In many cases all printable Unicode characters are invalid input.

Even if you represented valid strings safely using type MyAlphaString = MyAlphaString String. Writing a fuzzer for MyAlphaString is not straightforward.

Would you accept a PR in this direction? or prefer it as a separate package?

[Discussion] testEach / describeEach

TL;DR

Should we add syntactic sugar to test input-to-expected-result tables?

Background

Jest recently included describe.each and test.each. Could it work for elm-test?

test.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])(
  '.add(%i, %i)',
  (a, b, expected) => {
    expect(a + b).toBe(expected);
  },
);

Examples

Example: Generic

Polymorph in its argument: testEach : String -> List a -> (a -> Expect.Expectation) -> List Test

module SearchTest exposing (all)

import Expect
import Search exposing (Filter(..), toFilters)
import Test exposing (Test, describe, test)



-- usage example


all : Test
all =
    describe "Search"
        [ describe "test toFilters"
            (testEach "toFilters"
                [ ( "", [] )
                , ( " ", [] )
                , ( "a", [ TextFilter "a" ] )
                , ( "a b", [ TextFilter "a", TextFilter "b" ] )
                ]
             <|
                \( a, b ) ->
                    a
                        |> toFilters
                        |> Expect.equal b
            )
        ]



-- test each implementation


testEach : String -> List a -> (a -> Expect.Expectation) -> List Test
testEach name table fn =
    let
        toTest item =
            let
                testName =
                    name ++ " for input " ++ toString item
            in
            test testName <|
                \_ ->
                    fn item
    in
    List.map toTest table

Example: Constrained

Would work with fixed tuples. testEach : String -> List ( a, b ) -> (a -> b) -> List Test

module SearchTest exposing (all)

import Expect
import Search exposing (Filter(..), toFilters)
import Test exposing (Test, describe, test)



-- usage example


all : Test
all =
    describe "Search"
        [ describe "test toFilters"
            (testEach "toFilters"
                [ ( "", [] )
                , ( " ", [] )
                , ( "a", [ TextFilter "a" ] )
                , ( "a b", [ TextFilter "a", TextFilter "b" ] )
                ]
                toFilters
            )
        ]



-- test each implementation


testEach : String -> List ( a, b ) -> (a -> b) -> List Test
testEach name table fn =
    let
        toTest (( input, expectedResult ) as tuple) =
            let
                testName =
                    name ++ " for input " ++ toString tuple
            in
            test testName <|
                \_ ->
                    fn input |> Expect.equal expectedResult
    in
    List.map toTest table

Open questions

  • How would the api look like? Should it be restrained to List of tuples, which would lead to more variants?
  • Should the api be constrained to Expect.equal only?
  • What tests are possible that aren't better be solved with fuzz testing?
  • Is it worth adding sugar? Will people be write less boilerplate and test suites that are easier to understand?
  • How to create the test name, especially in 0.19?

Query.has and Query.hasNot seem to query children as well

I'm running into an issue where the following test case is failing when, based on the documentation for the has and hasNot functions, it should be passing. The following is the test case itself and after is the relevant console log.

table
  |> Query.fromHtml
  |> Query.find [ Selector.tag "thead" ]
  |> Query.find [ Selector.tag "tr" ]
  |> Query.hasNot [ Selector.attribute (Aria.colIndex 1) ]
> Table
> colindex on tr
> is not added for a non contiguous heading list

    โ–ผ Query.fromHtml

        <table aria-colcount="5" aria-rowcount="1">
            <thead>
                <tr>
                    <th aria-colindex="1">
                        label
                    </th>
                    <th aria-colindex="3">
                        label
                    </th>

                    <th aria-colindex="5">
                        label
                    </th>
                </tr>
            </thead>
            <tbody>
                <tr aria-rowindex="2">
                </tr>
            </tbody>
        </table>


    โ–ผ Query.find [ tag "thead" ]

        1)  <thead>
                <tr>
                    <th aria-colindex="1">
                        label
                    </th>
                    <th aria-colindex="3">
                        label
                    </th>
                    <th aria-colindex="5">
                        label
                    </th>
                </tr>
            </thead>


    โ–ผ Query.find [ tag "tr" ]

        1)  <tr>
                <th aria-colindex="1">
                    label
                </th>
                <th aria-colindex="3">
                    label
                </th>
                <th aria-colindex="5">
                    label
                </th>
            </tr>


    โ–ผ Query.hasNot [ attribute "aria-colindex" "1" ]

    > has not attribute "aria-colindex" "1"

My thought is that this would pass because the tr tag does not have a aria-colindex attribute. This is a similar case shown in the documentation for the package, but is not executing as expected. After playing with it a bit I figure out that it was due to the fact that there was a child th element that did have a aria-colindex="1" which makes the test fail. The only way I've been able to get around this issue is to modify the table's structure to not include the child th tags, but this is not ideal.

I'm kind of asking 2 questions here which is

  1. Is this functionality expected?
  2. If it is, than how would you recommend testing for an attribute to not be on an element?

usesFloat incorrectly identifies union type as a float

The logic elm-test uses to identify floats incorrectly identifies a union type with a potential value of Infinity as a float. This is because String.toFloat "Infinity" == Just Infinity.

This error only happens when the name of the union potential value is Infinity.

SSCE

module Example exposing (..)

import Expect exposing (Expectation)
import Fuzz exposing (Fuzzer, int, list, string)
import Test exposing (..)

type UnionType =
    Infinity

suite : Test
suite =
    test "should not give a 'use float' error" <|
        \() ->
            Infinity
                |> Expect.equal Infinity

Running elm-test with the latest (beta) version gives:

Running 1 test. To reproduce these results, run: elm-test --fuzz 100 --seed 241676437961883

โ†“ Example
โœ— should not give a 'use float' error

    Do not use Expect.equal with floats. Use Float.within instead.

I do not know what the solution is for this, I just renamed my union types as a work around.

ReadMe still references elm-package.json and copying dependencies

Hi,

The readme still talks about elm-package.json, even thought 0.19 uses elm.json files. And it still talks about copying dependencies between your main and test elm-package.json files, even though we can use one elm.json in 0.19

I would make the PR myself, but I am currently trying to figure out how to do tests with 0.19 myself, so I dont really know how to instruct others.

Fuzz.int generates values outside of Int32 range

The documentation for Fuzz.int states that it generates any 32 bit signed integer value but I've found that it can generate the value 2147483648 which is one greater than largest maximum Int32 value.

elm-test version: 1.2.0
OS: Windows 10

Running `elm-test init` without elm installed locally

I always install Elm locally in my projects and run it from ./node_modules/.bin. For this to work with elm-test I use the --compiler flag, though it seems this doesn't work with the elm-test init command.

$ ./node_modules/.bin/elm-test init --compiler ./node_modules/.bin/elm
/bin/sh: 1: elm: not found
Unable to create temporary directory for elm-test install. { Error: Command failed: elm install elm-explorations/test
    at checkExecSyncError (child_process.js:603:11)
    at Object.execSync (child_process.js:640:13)
    at Object.install (/home/louis/src/waive/assets/node_modules/elm-test/lib/install.js:54:19)
    at Object.<anonymous> (/home/louis/src/waive/assets/node_modules/elm-test/lib/elm-test.js:160:11)
    at Module._compile (internal/modules/cjs/loader.js:702:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:713:10)
    at Module.load (internal/modules/cjs/loader.js:612:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:551:12)
    at Function.Module._load (internal/modules/cjs/loader.js:543:3)
    at Module.require (internal/modules/cjs/loader.js:650:17)
    at require (internal/modules/cjs/helpers.js:20:18)
    at Object.<anonymous> (/home/louis/src/waive/assets/node_modules/elm-test/bin/elm-test:3:1)
    at Module._compile (internal/modules/cjs/loader.js:702:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:713:10)
    at Module.load (internal/modules/cjs/loader.js:612:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:551:12)
    at Function.Module._load (internal/modules/cjs/loader.js:543:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:744:10)
    at startup (internal/bootstrap/node.js:238:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:572:3)
  status: 127,
  signal: null,
  output: [ null, null, null ],
  pid: 6077,
  stdout: null,
  stderr: null }

What's the recommended method for using elm-test init without globally install Elm?

โ€œMaximum call stack size exceededโ€ on comparison of large data structures

I stumbled across this crash when I migrated one of my Elm projects to 0.19. This is the test I wrote with Elm 0.18, where it worked without problems: https://gitlab.com/MazeChaZer/knobster/blob/8d39fa8de9f5744cdaff45755b23050f4d9d06e0/tests/GridTest.elm

elm: 0.19.0
elm-explorations/test: 1.1.0
node-test-runner: 0.19.0-beta8

SSCCE:

module Example exposing (suite)

import Expect
import Test exposing (..)


suite : Test
suite =
    test "foo bar" <|
        \() ->
            Expect.equal
                [ [ { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  ]
                , [ { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  ]
                , [ { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  ]
                , [ { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  ]
                , [ { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  ]
                , [ { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  , { foo = "foo", bar = "bar" }
                  ]
                ]
                []

Output:

$ elm-test
Success!
Success! Compiled 1 module.

elm-test 0.19.0-beta8
---------------------

Running 1 test. To reproduce these results, run: elm-test --fuzz 100 --seed 195384286911629

[project]/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:3665
                        var change = function () {
                                              ^

RangeError: Maximum call stack size exceeded
    at [project]/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:3665:26
    at Function.f ([project]/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:3707:5)
    at A5 ([project]/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:113:28)
    at [project]/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:3711:13
    at Function.f ([project]/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:3648:11)
    at A2 ([project]/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:104:28)
    at Function.f ([project]/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:3708:11)
    at A5 ([project]/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:113:28)
    at [project]/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:3711:13
    at Function.f ([project]/elm-stuff/generated-code/elm-explorations/test/elmTestOutput.js:3648:11)


There was an unexpected runtime exception while running tests

A normal == comparison is no problem with this data structure: https://ellie-app.com/3fQ2FSpkxYca1

Re-add Fuzz.andThen?

It's nontrivial to get Fuzz.andThen working in 0.19 because the 0.18 version implementation relied on Debug.crash.

Perhaps we should re-add Fuzz.andThen as a MINOR release, with more helpful error messages in the event that you give it an invalid fuzzer.

Idea: Use `Range` to create (some) Fuzzers

I'm a fan of hedgehog [1] and I think it gets a lot of things right.

One of those is having a Range parameter for all fuzzers (i.e. Gens) that generate values with some notion of a range: integers, floats, strings, lists and other collection types.

Thus, there is no int : Fuzzer Int.
Only int : Range Int -> Fuzzer Int.

In hedgehog, internally a Range is defined as (translated to Elm):

type Size
    = Size Int


type Range a
    = Range a (Size -> ( a, a ))

Here Size is essentially the number of runs.
In Range a boundsFunction:

  1. a is the "origin" value
  2. boundsFunction shrinks towards this "origin" a as Size goes down (example defaults are 0 for Ints, empty list for lists)

See [2] for a comment about how I understand Size being used in boundsFunction.

To construct a Range Int, you would use:

linear : Int -> Int -> Range Int
linear lo hi =
    linearFrom lo lo hi


linearFrom : Int -> Int -> Int -> Range Int
linearFrom origin lo hi = 
    Range origin (intBoundsFunction origin lo hi)

intBoundsFunction : Int -> Int -> Int -> (Size -> (Int, Int))
-- Not elaborated on purpose, you can see hedgehog source for how it's done in Haskell

IMO this has several advantages:

  1. You get shrinking "for free" as part of the boundsFunction, it's useful to look at the hedgehog source [3] to see how they do this using linear, linearFrom, exponential and exponentialFrom constructor functions.
  2. You end up with a more flexible and powerful API.
  3. It forces users to think about the range of values they want to generate, so that it matches the problem domain instead of assuming defaults. Both in terms of total range, but also the distribution of values.

I understand that a more flexible and powerful API also results in a more "complicated" API, and you might be trying to go with something simple and uncomplicated.

Hence posting this issue to gauge appetite.

No way to customize the path of test files

As far as I can tell, there is no way to customize the path where the tests are.

Previously, we could use the elm-test TESTFILES option, but that seems to look for tests directory now.

For example:

elm-test src/test/elm/**/*.elm
Error: /.../src/test/elm/tests does not exist. Please create a tests/ directory in your project root!

It would be nice if we could specify in elm.json: test-directories similar to source-directories option.

tests/elm.json still required for ALE to lint test files

I gather that test-dependencies has been added to elm.json (formerly elm-package.json) to separate test dependencies. This does indeed seem to be a better approach than maintaining tests/elm.json separately.

However, when using vim/ALE, I see import errors. ALE runs elm make under the hood. It looks to me like it is essentially:

$ elm make --output=/dev/null tests/Example.elm

Which produces the following error

-- UNKNOWN IMPORT -------------------------------------------- tests/Example.elm

The Example module has a bad import:

    import Test

I cannot find that module! Is there a typo in the module name?

The "source-directories" field of your elm.json tells me to look in directories
like src, but it is not in any of them. Maybe it is in a package that is not
installed yet?

Of course, elm-explorations/test is in test-dependencies, not dependencies.

By creating tests/elm.json with adjusted source-directories and dependencies, I can get the make command (and thereby ALE) to work. But this confuses elm-test and it fails with the following:

Error: /path/to/my/project/tests/tests does not exist. Please create a tests/ directory in your project root!

As a quick and dirty workaround, I have a bash function as follows:

elmtest() {
    mv tests/elm.json tests/elmjson
    elm-test "$@"
    mv tests/elmjson tests/elm.json
}

But this is obviously not the right solution.
Is there a (better) way to do this now?

Maximum call stack size exceeded with Test.fuzz2

SSCCE:

module Example exposing (suite)

import Expect 
import Fuzz
import Test exposing (..)

suite : Test
suite =
    fuzz2 Fuzz.float (Fuzz.floatRange -1.0e100 1.0e100) "should not run out of stack" <|
        \a b ->
            Expect.fail "always fail"

Expected

Test to fail

Actual

elm-test 0.19.0-beta8
---------------------

Running 1 test. To reproduce these results, run: elm-test --fuzz 100 --seed 48737553166794

โ†“ Example
โœ— should not run out of stack

    This test failed because it threw an exception: "RangeError: Maximum call stack size exceeded"

Notes

  • This only occurs when a test fails.
  • Changing floatRange to float fixes this.
  • Possibly related #22

elm-html-test README.md

@avh4 did a great job moving elm-html-test into elm-explorations/test (thx ๐Ÿ‘ ).

If I'm not mistaken the README.md of that package got lost. It explains the general usage of the package.

We could:

  1. Add it to the README.md (but it will bloat it)
  2. Add it to a package (e.g. Query) (but it has to be part of the elm file).
  3. Add it as separate markdown file and link to it from the main README.md (my favorite)

Testing any value containing a Process.Id

The issue is similar to this one: #24

We have a model containing a Process.Id (so that we can kill/restart it), but there is no way to create one for testing, since the Platform module don't export the constructor, which makes perfectly sense when you target production code, but not in the context of testing.

A very generic solution to this kind of problems would be to add conditional compilation, so that instead of:

module Platform exposing
    ( Program
    , ...
    , ProcessId
    , ...
    )

We could write:

module Platform exposing
    ( Program
    , ...
# if env == test then
    , ProcessId(..)
# else
    , ProcessId
# end
    , ...
    )

Notice that this would solve a lot of other problems (like #24, Debug.log calls, etc...).

Html test fails (possibly due to lazy containing keyed node containing lazy?)

Any Html test I run fails with the message below

    โ–ผ Query.fromHtml

        Internal Error: failed to decode the virtual dom.  
        Please report this at <https://github.com/elm-explorations/test/issues>. 
        Problem with the value at json.e[2].e[0].e[0].k.e[0].e[0].k:

            undefined

        Expecting an OBJECT with a field named `$`


    โ–ผ Internal Error: failed to decode the virtual dom.  
        Please report this at <https://github.com/elm-explorations/test/issues>


    โ–ผ Problem with the value at json.e[2].e[0].e[0].k.e[0].e[0].k:

        undefined

    Expecting an OBJECT with a field named `$`

The test is:

describeHeaders =
    [ describe "headers"
        [ test "should contain a container with three child divs" <|
            \() ->
                view model
                    |> Query.fromHtml
                    |> Query.findAll [ class "header" ]
                    |> Query.index 0
                    |> Query.has [ text "Score" ]
        ]
    ]

but I've got the same error whatever the test is.

Need exclusive range fuzzers

I have a test where I move an item from a custom collection into another (this neccessitates changing IDs, which is why it is a special function). I generate two lists of strings to be converted into my collection and then grab a random index from the first collection to be moved into the second.

To determine the index of the item to move, I use a percentage fuzzer. However, the test fails because of the edge case of the percentage being 1, where flooring the List.length * percent doesn't help and neccessitates an extra conditional to work around the edge case.

I feel like there might be a more elegant way to choose an index. But I also think that exclusive range fuzzers might be useful in other situations as well, so I thought that this use case might motivate discussion around them.

Anything with Browser.Navigation.Key cannot be tested

When using Browser.application I will put the Key in my model for later use.

When testing I want to create a model, but I don't have a way to get a Key.
So I cannot test functions that take my Model.

Can test provide a way to get a navigation key?

Originally opened this here elm/browser#30

Improve Expect.equal's diff display

When viewing a diff, I frequently forget which one is the actual value and which the expected one.

There are two similar alternatives that are popular that both use the pipe operator in the display and that are both compatible with the reasoning that the current output is based on:

"first value"
โ•ท
โ”‚ |> Expect.equal
โ•ต
"second value"
"first value"
|> Expect.equal
"second value"

In order to play around with alternatives, check out the Ellie.

Simulate event bubbling?

Someone suggested simulating event bubbling in html tests.

The basic idea would be:

  • I have <div onClick=...><button/></div> in my vdom
  • In a test, I simulate a click on the child <button/>
  • Since the onClick handler on the parent <div> would trigger in the real world, I should be able to write a test verifying that it triggered

In this world, presumably stopPropagation would need to be processed and handled properly.

Thoughts?

Any way to test the result of a Fuzz.maybe or force a Just?

I think my case may be another +1 for #17, but perhaps there's another way to go about this.

How should one formulate fuzz tests with the dependence of one maybe type on another type?

My case:

type Position
     = Delta Int Int (List Int)
     | Coordinate Float Float (List Float)

type alias Transform =
    { ... }

fuzzTransform : Fuzzer (Maybe Transform)

fuzzPosition : Fuzzer Position

I'd like to pattern match the fuzzTransform in the fuzzPosition fuzzer, perhaps like this:

fuzzPosition : Maybe Transform -> Fuzzer Position
fuzzPosition transform =
    case transform of
        Just _ ->
            fuzzDelta
        Nothing ->
            fuzzCoordinate

I don't see how to do this without Fuzz.andThen, nor if I were to use a custom fuzzer. Is there a way to perhaps use something like:

fuzzTransform : Fuzzer Transform

fuzzPosition : Fuzzer Position
fuzzPosition  =
    Fuzz.frequency
        [ ( 1, positionHelper Nothing )
        , ( 3, positionHelper (Just fuzzTransform) )
        ]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.