Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New style like "fun spec", but with "should" #6

Closed
helmbold opened this issue Apr 15, 2016 · 8 comments
Closed

New style like "fun spec", but with "should" #6

helmbold opened this issue Apr 15, 2016 · 8 comments
Assignees
Labels
enhancement ✨ Suggestions for adding new features or improving existing ones.

Comments

@helmbold
Copy link
Contributor

I've pretty good experience writing unit test methods starting with should. This simple words leads to much better names compared to test. Therefore I suggest, to support another style like fun spec, but using the word should. Example:

should("remove the last element from stack") {
  val stack = ListStack<String>()
  stack.push("hello")
  stack.push("world")
  stack.size() shouldBe 2

  val element = stack.pop() 

  element shouldBe "world"
  stack.size() shouldBe 1
}

Compared to the existing style with test it is even more concise, since it is already known what object is tested in a certain unit test class.

should("remove the last element from stack")
test("ListStack.pop should remove the last element from stack")
@sksamuel
Copy link
Member

I like it, what do you suggest this *Spec should be called

On 15 April 2016 at 07:32, Christian Helmbold notifications@github.com
wrote:

I've pretty good experience writing unit test methods starting with should.
This simple words leads to much better names compared to test. Therefore
I suggest, to support another style like fun spec, but using the word
should. Example:

should("remove the last element from stack") {
val stack = ListStack()
stack.push("hello")
stack.push("world")
stack.size() shouldBe 2

val element = stack.pop()

element shouldBe "world"
stack.size() shouldBe 1
}

Compared to the existing style with test it is even more concise, since
it is already known what object is tested in a certain unit test class.

should("remove the last element from stack")
test("ListStack.pop should remove the last element from stack")


You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub
#6

@helmbold
Copy link
Contributor Author

helmbold commented Apr 15, 2016

It is hard to find a good name. On the other hand, if I read "fun spec", I have no idea, how the code could look like. So maybe it is enough if the name is useful for developers already knowing the different styles.

Here are my suggestions:

  • should spec
  • should fun spec
  • fun should spec
  • should simple spec
  • simple should spec

I prefer "should spec" since it describes pretty good what is typical for this style: the word "should". On the other hand "should" is used by the other styles, too. Maybe "should fun spec" is a bit more descriptive. Since I find this kind of spec most simple, the word "simple" could be used, but then again "fun spec" wouldn't be appropriate, because it is as simple as my suggested style.

@sksamuel
Copy link
Member

I think ShouldSpec is fine.
On 15 Apr 2016 15:27, "Christian Helmbold" notifications@github.com wrote:

It is hard to find a good name. On the other hand, if I read "fun spec", I
have no idea, how the code could look like. So maybe it is enough if the
name is useful for developers already knowing the different styles.

Here are my suggestions:

  • should spec
  • should fun spec
  • fun should spec
  • should simple spec
  • simple should spec

I prefer "should spec" since it describes pretty good what is typical for
this style: the word "should". Whether it is a variant of "fun spec" is not
that important. Since I find this kind of spec most simple, the word
"simple" could be used.


You are receiving this because you commented.
Reply to this email directly or view it on GitHub
#6 (comment)

@sksamuel sksamuel added the enhancement ✨ Suggestions for adding new features or improving existing ones. label Apr 15, 2016
@sksamuel sksamuel self-assigned this Apr 15, 2016
@helmbold
Copy link
Contributor Author

Fine! I'm looking forward to the new style. Thanks for your effort.

sksamuel added a commit that referenced this issue Apr 15, 2016
@sksamuel
Copy link
Member

sksamuel commented Apr 16, 2016

This changes allows

should("some test") { }

and

"some text" {
   should("some test") { }
}

@sksamuel
Copy link
Member

@helmbold did you try this out of interest?

@helmbold
Copy link
Contributor Author

... sorry, not yet. My job is still Java dominated ... However I'm planning to use it in the near future.

@sksamuel
Copy link
Member

booo to java :)

ajalt referenced this issue in ajalt/kotlintest Jul 13, 2018
The current string shrink algorithm generates candidates by dropping single characters from the end of the input. This doesn't produce the smallest case, since it doesn't drop characters from the start of the string. It is also linear on the size of the input, so it requires a potentially large number of tries to reach the result it does produce.

This PR changes to algorithm to bisect the input string from both directions, producing a minimal output in log n tries.

As an example of the current behavior, the test:

`forAll { it: String -> !it.contains("#") }`

produces output like this:

```
Attempting to shrink failed arg DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2yEcNn18+B*w,1x,L;6&k<}QQxU+!) e|Gr+ tri7jw{
Shrink #1: <empty string> pass
Shrink #2: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2yEcNn18+B*w,1x,L;6&k<}QQxU+!) e|Gr+ tri7 fail
Shrink #3: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2yEcNn18+B*w,1x,L;6&k<}QQxU+!) e|Gr+ fail
Shrink #4: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2yEcNn18+B*w,1x,L;6&k<}QQxU+!)  fail
Shrink #5: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2yEcNn18+B*w,1x,L;6&k<}QQx fail
Shrink #6: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2yEcNn18+B*w,1x,L;6&k fail
Shrink #7: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2yEcNn18+B*w,1x, fail
Shrink #8: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2yEcNn18+B* fail
Shrink #9: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2yEcNn fail
Shrink #10: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2 fail
Shrink #11: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M# fail
Shrink #12: DPn CPQ7hBAY&LP;7MxPtN^Oy\$ pass
Shrink #13: DPn CPQ7hBAY&LP;7MxPtN^Oy\$F pass
Shrink #14: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz pass
Shrink #15: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz; pass
Shrink #16: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M pass
Shrink #17: aaaaaDPn CPQ7hBAY&LP;7MxPtN^Oy\$ pass
Shrink #18: aaaaDPn CPQ7hBAY&LP;7MxPtN^Oy\$F pass
Shrink #19: aaaDPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz pass
Shrink #20: aaDPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz; pass
Shrink #21: aDPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M pass
Shrink result => DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#
```

This is 21 attempts to produce a string 32x longer than optimal.

The new algorithm produces output like this:

```
Attempting to shrink failed arg t ^j>t\o,x3?eb9#F'>g>vGQ-N}nkx
Shrink #1: <empty string> pass
Shrink #2: t ^j>t\o,x3?eb9 pass
Shrink #3: #F'>g>vGQ-N}nkx fail
Shrink #4: #F'>g>vG fail
Shrink #5: #F'> fail
Shrink #6: #F fail
Shrink #7: # fail
Shrink result => #
```

This is only 7 tries, and produces the correct output of `"#"`
sksamuel pushed a commit that referenced this issue Jul 15, 2018
The current string shrink algorithm generates candidates by dropping single characters from the end of the input. This doesn't produce the smallest case, since it doesn't drop characters from the start of the string. It is also linear on the size of the input, so it requires a potentially large number of tries to reach the result it does produce.

This PR changes to algorithm to bisect the input string from both directions, producing a minimal output in log n tries.

As an example of the current behavior, the test:

`forAll { it: String -> !it.contains("#") }`

produces output like this:

```
Attempting to shrink failed arg DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2yEcNn18+B*w,1x,L;6&k<}QQxU+!) e|Gr+ tri7jw{
Shrink #1: <empty string> pass
Shrink #2: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2yEcNn18+B*w,1x,L;6&k<}QQxU+!) e|Gr+ tri7 fail
Shrink #3: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2yEcNn18+B*w,1x,L;6&k<}QQxU+!) e|Gr+ fail
Shrink #4: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2yEcNn18+B*w,1x,L;6&k<}QQxU+!)  fail
Shrink #5: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2yEcNn18+B*w,1x,L;6&k<}QQx fail
Shrink #6: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2yEcNn18+B*w,1x,L;6&k fail
Shrink #7: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2yEcNn18+B*w,1x, fail
Shrink #8: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2yEcNn18+B* fail
Shrink #9: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2yEcNn fail
Shrink #10: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#EC\M2 fail
Shrink #11: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M# fail
Shrink #12: DPn CPQ7hBAY&LP;7MxPtN^Oy\$ pass
Shrink #13: DPn CPQ7hBAY&LP;7MxPtN^Oy\$F pass
Shrink #14: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz pass
Shrink #15: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz; pass
Shrink #16: DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M pass
Shrink #17: aaaaaDPn CPQ7hBAY&LP;7MxPtN^Oy\$ pass
Shrink #18: aaaaDPn CPQ7hBAY&LP;7MxPtN^Oy\$F pass
Shrink #19: aaaDPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz pass
Shrink #20: aaDPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz; pass
Shrink #21: aDPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M pass
Shrink result => DPn CPQ7hBAY&LP;7MxPtN^Oy\$Fz;M#
```

This is 21 attempts to produce a string 32x longer than optimal.

The new algorithm produces output like this:

```
Attempting to shrink failed arg t ^j>t\o,x3?eb9#F'>g>vGQ-N}nkx
Shrink #1: <empty string> pass
Shrink #2: t ^j>t\o,x3?eb9 pass
Shrink #3: #F'>g>vGQ-N}nkx fail
Shrink #4: #F'>g>vG fail
Shrink #5: #F'> fail
Shrink #6: #F fail
Shrink #7: # fail
Shrink result => #
```

This is only 7 tries, and produces the correct output of `"#"`
sksamuel pushed a commit that referenced this issue Nov 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement ✨ Suggestions for adding new features or improving existing ones.
Projects
None yet
Development

No branches or pull requests

2 participants