Skip to content

Commit 29bf875

Browse files
committed
Add TaskSeq.Length tests, fix implementation, an update bunch more tests to use test-data providers
1 parent 027be48 commit 29bf875

File tree

8 files changed

+186
-120
lines changed

8 files changed

+186
-120
lines changed

src/FSharpy.TaskSeq.Test/FSharpy.TaskSeq.Test.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<Compile Include="TaskSeq.Item.Tests.fs" />
2323
<Compile Include="TaskSeq.Iter.Tests.fs" />
2424
<Compile Include="TaskSeq.Last.Tests.fs" />
25+
<Compile Include="TaskSeq.Length.Tests.fs" />
2526
<Compile Include="TaskSeq.Map.Tests.fs" />
2627
<Compile Include="TaskSeq.Pick.Tests.fs" />
2728
<Compile Include="TaskSeq.Zip.Tests.fs" />
Lines changed: 65 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module FSharpy.Tests.Head
1+
module FSharpy.Tests.ExactlyOne
22

33
open System
44
open Xunit
@@ -9,49 +9,91 @@ open FSharpy
99

1010

1111
[<Fact>]
12-
let ``TaskSeq-head throws on empty sequences`` () = task {
13-
fun () -> TaskSeq.empty<string> |> TaskSeq.head |> Task.ignore
12+
let ``TaskSeq-exactlyOne throws on empty sequences`` () = task {
13+
fun () -> TaskSeq.empty<string> |> TaskSeq.exactlyOne |> Task.ignore
1414
|> should throwAsyncExact typeof<ArgumentException>
1515
}
1616

1717
[<Fact>]
18-
let ``TaskSeq-head throws on empty sequences - variant`` () = task {
19-
fun () -> taskSeq { do () } |> TaskSeq.head |> Task.ignore
18+
let ``TaskSeq-exactlyOne throws on empty sequences - variant`` () = task {
19+
fun () -> taskSeq { do () } |> TaskSeq.exactlyOne |> Task.ignore
2020
|> should throwAsyncExact typeof<ArgumentException>
2121
}
2222

2323
[<Fact>]
24-
let ``TaskSeq-tryHead returns None on empty sequences`` () = task {
25-
let! nothing = TaskSeq.empty<string> |> TaskSeq.tryHead
24+
let ``TaskSeq-tryExactlyOne returns None on empty sequences`` () = task {
25+
let! nothing = TaskSeq.empty<string> |> TaskSeq.tryExactlyOne
2626
nothing |> should be None'
2727
}
2828

2929
[<Fact>]
30-
let ``TaskSeq-head gets the first item in a longer sequence`` () = task {
31-
let! head = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 |> TaskSeq.head
30+
let ``TaskSeq-exactlyOne throws for a sequence of length = two`` () = task {
31+
fun () ->
32+
taskSeq {
33+
yield 1
34+
yield 2
35+
}
36+
|> TaskSeq.exactlyOne
37+
|> Task.ignore
38+
|> should throwAsyncExact typeof<ArgumentException>
39+
}
40+
41+
[<Fact>]
42+
let ``TaskSeq-exactlyOne throws for a sequence of length = two - variant`` () = task {
43+
fun () ->
44+
createDummyTaskSeqWith 50L<µs> 1000L<µs> 2
45+
|> TaskSeq.exactlyOne
46+
|> Task.ignore
47+
|> should throwAsyncExact typeof<ArgumentException>
48+
}
49+
50+
51+
[<Fact>]
52+
let ``TaskSeq-exactlyOne throws with a larger sequence`` () = task {
53+
fun () ->
54+
createDummyTaskSeqWith 50L<µs> 300L<µs> 200
55+
|> TaskSeq.exactlyOne
56+
|> Task.ignore
57+
|> should throwAsyncExact typeof<ArgumentException>
58+
}
3259

33-
head |> should equal 1
60+
[<Fact>]
61+
let ``TaskSeq-tryExactlyOne returns None with a larger sequence`` () = task {
62+
let! nothing =
63+
createDummyTaskSeqWith 50L<µs> 300L<µs> 20
64+
|> TaskSeq.tryExactlyOne
65+
66+
nothing |> should be None'
3467
}
3568

3669
[<Fact>]
37-
let ``TaskSeq-head gets the only item in a singleton sequence`` () = task {
38-
let! head = taskSeq { yield 10 } |> TaskSeq.head
39-
head |> should equal 10
70+
let ``TaskSeq-exactlyOne gets the only item in a singleton sequence`` () = task {
71+
let! exactlyOne = taskSeq { yield 10 } |> TaskSeq.exactlyOne
72+
exactlyOne |> should equal 10
4073
}
4174

4275
[<Fact>]
43-
let ``TaskSeq-tryHead gets the first item in a longer sequence`` () = task {
44-
let! head =
45-
createDummyTaskSeqWith 50L<µs> 1000L<µs> 50
46-
|> TaskSeq.tryHead
76+
let ``TaskSeq-tryExactlyOne gets the only item in a singleton sequence`` () = task {
77+
let! exactlyOne = taskSeq { yield 10 } |> TaskSeq.tryExactlyOne
78+
exactlyOne |> should be Some'
79+
exactlyOne |> should equal (Some 10)
80+
}
81+
82+
[<Fact>]
83+
let ``TaskSeq-exactlyOne gets the only item in a singleton sequence - variant`` () = task {
84+
let! exactlyOne =
85+
createLongerDummyTaskSeq 50<ms> 300<ms> 1
86+
|> TaskSeq.exactlyOne
4787

48-
head |> should be Some'
49-
head |> should equal (Some 1)
88+
exactlyOne |> should equal 1
5089
}
5190

5291
[<Fact>]
53-
let ``TaskSeq-tryHead gets the only item in a singleton sequence`` () = task {
54-
let! head = taskSeq { yield 10 } |> TaskSeq.tryHead
55-
head |> should be Some'
56-
head |> should equal (Some 10)
92+
let ``TaskSeq-tryExactlyOne gets the only item in a singleton sequence - variant`` () = task {
93+
let! exactlyOne =
94+
createLongerDummyTaskSeq 50<ms> 300<ms> 1
95+
|> TaskSeq.tryExactlyOne
96+
97+
exactlyOne |> should be Some'
98+
exactlyOne |> should equal (Some 1)
5799
}
Lines changed: 23 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module FSharpy.Tests.ExactlyOne
1+
module FSharpy.Tests.Head
22

33
open System
44
open Xunit
@@ -9,91 +9,49 @@ open FSharpy
99

1010

1111
[<Fact>]
12-
let ``TaskSeq-exactlyOne throws on empty sequences`` () = task {
13-
fun () -> TaskSeq.empty<string> |> TaskSeq.exactlyOne |> Task.ignore
12+
let ``TaskSeq-head throws on empty sequences`` () = task {
13+
fun () -> TaskSeq.empty<string> |> TaskSeq.head |> Task.ignore
1414
|> should throwAsyncExact typeof<ArgumentException>
1515
}
1616

1717
[<Fact>]
18-
let ``TaskSeq-exactlyOne throws on empty sequences - variant`` () = task {
19-
fun () -> taskSeq { do () } |> TaskSeq.exactlyOne |> Task.ignore
18+
let ``TaskSeq-head throws on empty sequences - variant`` () = task {
19+
fun () -> taskSeq { do () } |> TaskSeq.head |> Task.ignore
2020
|> should throwAsyncExact typeof<ArgumentException>
2121
}
2222

2323
[<Fact>]
24-
let ``TaskSeq-tryExactlyOne returns None on empty sequences`` () = task {
25-
let! nothing = TaskSeq.empty<string> |> TaskSeq.tryExactlyOne
24+
let ``TaskSeq-tryHead returns None on empty sequences`` () = task {
25+
let! nothing = TaskSeq.empty<string> |> TaskSeq.tryHead
2626
nothing |> should be None'
2727
}
2828

2929
[<Fact>]
30-
let ``TaskSeq-exactlyOne throws for a sequence of length = two`` () = task {
31-
fun () ->
32-
taskSeq {
33-
yield 1
34-
yield 2
35-
}
36-
|> TaskSeq.exactlyOne
37-
|> Task.ignore
38-
|> should throwAsyncExact typeof<ArgumentException>
39-
}
40-
41-
[<Fact>]
42-
let ``TaskSeq-exactlyOne throws for a sequence of length = two - variant`` () = task {
43-
fun () ->
44-
createDummyTaskSeqWith 50L<µs> 1000L<µs> 2
45-
|> TaskSeq.exactlyOne
46-
|> Task.ignore
47-
|> should throwAsyncExact typeof<ArgumentException>
48-
}
49-
50-
51-
[<Fact>]
52-
let ``TaskSeq-exactlyOne throws with a larger sequence`` () = task {
53-
fun () ->
54-
createDummyTaskSeqWith 50L<µs> 300L<µs> 200
55-
|> TaskSeq.exactlyOne
56-
|> Task.ignore
57-
|> should throwAsyncExact typeof<ArgumentException>
58-
}
30+
let ``TaskSeq-head gets the first item in a longer sequence`` () = task {
31+
let! head = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 |> TaskSeq.head
5932

60-
[<Fact>]
61-
let ``TaskSeq-tryExactlyOne returns None with a larger sequence`` () = task {
62-
let! nothing =
63-
createDummyTaskSeqWith 50L<µs> 300L<µs> 20
64-
|> TaskSeq.tryExactlyOne
65-
66-
nothing |> should be None'
33+
head |> should equal 1
6734
}
6835

6936
[<Fact>]
70-
let ``TaskSeq-exactlyOne gets the only item in a singleton sequence`` () = task {
71-
let! exactlyOne = taskSeq { yield 10 } |> TaskSeq.exactlyOne
72-
exactlyOne |> should equal 10
37+
let ``TaskSeq-head gets the only item in a singleton sequence`` () = task {
38+
let! head = taskSeq { yield 10 } |> TaskSeq.head
39+
head |> should equal 10
7340
}
7441

7542
[<Fact>]
76-
let ``TaskSeq-tryExactlyOne gets the only item in a singleton sequence`` () = task {
77-
let! exactlyOne = taskSeq { yield 10 } |> TaskSeq.tryExactlyOne
78-
exactlyOne |> should be Some'
79-
exactlyOne |> should equal (Some 10)
80-
}
81-
82-
[<Fact>]
83-
let ``TaskSeq-exactlyOne gets the only item in a singleton sequence - variant`` () = task {
84-
let! exactlyOne =
85-
createLongerDummyTaskSeq 50<ms> 300<ms> 1
86-
|> TaskSeq.exactlyOne
43+
let ``TaskSeq-tryHead gets the first item in a longer sequence`` () = task {
44+
let! head =
45+
createDummyTaskSeqWith 50L<µs> 1000L<µs> 50
46+
|> TaskSeq.tryHead
8747

88-
exactlyOne |> should equal 1
48+
head |> should be Some'
49+
head |> should equal (Some 1)
8950
}
9051

9152
[<Fact>]
92-
let ``TaskSeq-tryExactlyOne gets the only item in a singleton sequence - variant`` () = task {
93-
let! exactlyOne =
94-
createLongerDummyTaskSeq 50<ms> 300<ms> 1
95-
|> TaskSeq.tryExactlyOne
96-
97-
exactlyOne |> should be Some'
98-
exactlyOne |> should equal (Some 1)
53+
let ``TaskSeq-tryHead gets the only item in a singleton sequence`` () = task {
54+
let! head = taskSeq { yield 10 } |> TaskSeq.tryHead
55+
head |> should be Some'
56+
head |> should equal (Some 10)
9957
}

src/FSharpy.TaskSeq.Test/TaskSeq.Last.Tests.fs

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,45 +8,36 @@ open FsToolkit.ErrorHandling
88
open FSharpy
99

1010

11-
[<Fact>]
12-
let ``TaskSeq-last throws on empty sequences`` () = task {
13-
fun () -> TaskSeq.empty<string> |> TaskSeq.last |> Task.ignore
14-
|> should throwAsyncExact typeof<ArgumentException>
15-
}
16-
17-
[<Fact>]
18-
let ``TaskSeq-last throws on empty sequences - variant`` () = task {
19-
fun () -> taskSeq { do () } |> TaskSeq.last |> Task.ignore
11+
[<Theory; ClassData(typeof<TestEmptyVariants>)>]
12+
let ``TaskSeq-last throws on empty sequences`` variant = task {
13+
fun () -> getEmptyVariant variant |> TaskSeq.last |> Task.ignore
2014
|> should throwAsyncExact typeof<ArgumentException>
2115
}
2216

23-
[<Fact>]
24-
let ``TaskSeq-tryLast returns None on empty sequences`` () = task {
25-
let! nothing = TaskSeq.empty<string> |> TaskSeq.tryLast
17+
[<Theory; ClassData(typeof<TestEmptyVariants>)>]
18+
let ``TaskSeq-tryLast returns None on empty sequences`` variant = task {
19+
let! nothing = getEmptyVariant variant |> TaskSeq.tryLast
2620
nothing |> should be None'
2721
}
2822

29-
[<Fact>]
30-
let ``TaskSeq-last gets the last item in a longer sequence`` () = task {
31-
let! last = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 |> TaskSeq.last
32-
33-
last |> should equal 50
23+
[<Theory; ClassData(typeof<TestSmallVariants>)>]
24+
let ``TaskSeq-last gets the last item in a longer sequence`` variant = task {
25+
let! last = getSmallVariant variant |> TaskSeq.last
26+
last |> should equal 10
3427
}
3528

3629
[<Fact>]
3730
let ``TaskSeq-last gets the only item in a singleton sequence`` () = task {
38-
let! last = taskSeq { yield 10 } |> TaskSeq.last
39-
last |> should equal 10
31+
let! last = taskSeq { yield 42 } |> TaskSeq.last
32+
last |> should equal 42
4033
}
4134

42-
[<Fact>]
43-
let ``TaskSeq-tryLast gets the last item in a longer sequence`` () = task {
44-
let! last =
45-
createDummyTaskSeqWith 50L<µs> 1000L<µs> 50
46-
|> TaskSeq.tryLast
35+
[<Theory; ClassData(typeof<TestSmallVariants>)>]
36+
let ``TaskSeq-tryLast gets the last item in a longer sequence`` variant = task {
37+
let! last = getSmallVariant variant |> TaskSeq.tryLast
4738

4839
last |> should be Some'
49-
last |> should equal (Some 50)
40+
last |> should equal (Some 10)
5041
}
5142

5243
[<Fact>]
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
module FSharpy.Tests.Length
2+
3+
open System
4+
open Xunit
5+
open FsUnit.Xunit
6+
open FsToolkit.ErrorHandling
7+
8+
open FSharpy
9+
10+
11+
[<Theory; ClassData(typeof<TestEmptyVariants>)>]
12+
let ``TaskSeq-length returns zero on empty sequences`` variant = task {
13+
let! len = getEmptyVariant variant |> TaskSeq.length
14+
len |> should equal 0
15+
}
16+
17+
[<Theory; ClassData(typeof<TestEmptyVariants>)>]
18+
let ``TaskSeq-lengthBy returns zero on empty sequences`` variant = task {
19+
let! len = getEmptyVariant variant |> TaskSeq.lengthBy (fun _ -> true)
20+
len |> should equal 0
21+
}
22+
23+
[<Theory; ClassData(typeof<TestEmptyVariants>)>]
24+
let ``TaskSeq-lengthByAsync returns zero on empty sequences`` variant = task {
25+
let! len =
26+
getEmptyVariant variant
27+
|> TaskSeq.lengthByAsync (Task.apply (fun _ -> true))
28+
29+
len |> should equal 0
30+
}
31+
32+
[<Theory; ClassData(typeof<TestSmallVariants>)>]
33+
let ``TaskSeq-length returns proper length`` variant = task {
34+
let! len = getSmallVariant variant |> TaskSeq.length
35+
len |> should equal 10
36+
}
37+
38+
[<Theory; ClassData(typeof<TestSmallVariants>)>]
39+
let ``TaskSeq-lengthBy returns proper length`` variant = task {
40+
let! len = getSmallVariant variant |> TaskSeq.lengthBy (fun _ -> true)
41+
len |> should equal 10
42+
}
43+
44+
[<Theory; ClassData(typeof<TestSmallVariants>)>]
45+
let ``TaskSeq-lengthByAsync returns proper length`` variant = task {
46+
let! len =
47+
getSmallVariant variant
48+
|> TaskSeq.lengthByAsync (Task.apply (fun _ -> true))
49+
50+
len |> should equal 10
51+
}
52+
53+
[<Theory; ClassData(typeof<TestSmallVariants>)>]
54+
let ``TaskSeq-lengthBy returns proper length when filtering`` variant = task {
55+
let run f = getSmallVariant variant |> TaskSeq.lengthBy f
56+
let! len = run (fun x -> x % 3 = 0)
57+
len |> should equal 3 // [3; 6; 9]
58+
let! len = run (fun x -> x % 3 = 1)
59+
len |> should equal 4 // [1; 4; 7; 10]
60+
let! len = run (fun x -> x % 3 = 2)
61+
len |> should equal 3 // [2; 5; 8]
62+
}
63+
64+
[<Theory; ClassData(typeof<TestSmallVariants>)>]
65+
let ``TaskSeq-lengthByAsync returns proper length when filtering`` variant = task {
66+
let run f =
67+
getSmallVariant variant
68+
|> TaskSeq.lengthByAsync (Task.apply f)
69+
70+
let! len = run (fun x -> x % 3 = 0)
71+
len |> should equal 3 // [3; 6; 9]
72+
let! len = run (fun x -> x % 3 = 1)
73+
len |> should equal 4 // [1; 4; 7; 10]
74+
let! len = run (fun x -> x % 3 = 2)
75+
len |> should equal 3 // [2; 5; 8]
76+
}

0 commit comments

Comments
 (0)