SAFE Stack (link) のサンプルの ToDo アプリを眺める続きの続き。
テストのソースを見る。
対象のファイルは以下の 3 個。
ファイル | 行数 |
tests/Client/Client.Tests.fs | 28 |
tests/Server/Server.Tests.fs | 27 |
tests/Shared/Shared.Tests.fs | 15 |
合計 | 70 |
tests/Client/Client.Tests.fs
1 module Client.Tests
2
3 open Fable.Mocha
4
5 open Index
6 open Shared
7
8 let client = testList "Client" [
9 testCase "Added todo" <| fun _ ->
10 let newTodo = Todo.create "new todo"
11 let model, _ = init ()
12
13 let model, _ = update (AddedTodo newTodo) model
14
15 Expect.equal 1 model.Todos.Length "There should be 1 todo"
16 Expect.equal newTodo model.Todos.[0] "Todo should equal new todo"
17 ]
18
行番号 | コメント |
8 | testList の第2引数はリストで testCase やネストした testList を要素にもてる。 |
11 | init 関数でモデルを初期化。init 関数の中で作っている初期コマンド ( Cmd.OfAsync.perform todosApi.getTodos () GotTodos ) は無視していて、サーバの API も呼び出していない。モデルの ToDo 項目は空リストのまま。 |
13 | update 関数でメッセージを処理。本来、AddedTodo メッセージはサーバへの API 呼び出しが成功したときに返されるものだけど、ここでは直接 update 関数に渡している。 |
15, 16 | 更新後のモデルを検査。 |
19 let all =
20 testList "All"
21 [
22 #if FABLE_COMPILER // This preprocessor directive makes editor happy
23 Shared.Tests.shared
24 #endif
25 client
26 ]
27
28 [<EntryPoint>]
29 let main _ = Mocha.runTests all
行番号 | コメント |
22 | コメントの This preprocessor directive makes editor happy の理由が分からない。 |
23, 25 | testList の中にネストして別の testList を格納している。 |
29 | テストを実行。 |
tests/Server/Server.Tests.fs
1 module Server.Tests
2
3 open Expecto
4
5 open Shared
6 open Server
7
8 let server = testList "Server" [
9 testCase "Adding valid Todo" <| fun _ ->
10 let storage = Storage()
11 let validTodo = Todo.create "TODO"
12 let expectedResult = Ok ()
13
14 let result = storage.AddTodo validTodo
15
16 Expect.equal result expectedResult "Result should be ok"
17 Expect.contains (storage.GetTodos()) validTodo "Storage should contain new todo"
18 ]
19
行番号 | コメント |
10-17 | この ToDo アプリでは、サーバの storage とクライアントのモデルが大体同等で、テストもほぼ同じようなことをやろうとしている。ただ、サーバの storage が mutable、クライアントのモデルが immutable という違いがある。 |
20 let all =
21 testList "All"
22 [
23 Shared.Tests.shared
24 server
25 ]
26
27 [<EntryPoint>]
28 let main _ = runTests defaultConfig all
行番号 | コメント |
23 | サーバでは Shared.Tests.shared は無条件に参照している。クライアントが #if と #endif で括っていた理由がますます分からなくなった。 |
28 | テストを実行。 |
tests/Shared/Shared.Tests.fs
1 module Shared.Tests
2
3 #if FABLE_COMPILER
4 open Fable.Mocha
5 #else
6 open Expecto
7 #endif
8
9 open Shared
10
11 let shared = testList "Shared" [
12 testCase "Empty string is not a valid description" <| fun _ ->
13 let expected = false
14 let actual = Todo.isValid ""
15 Expect.equal actual expected "Should be false"
16 ]
行番号 | コメント |
3-7 | クライアントでは Fable.Mocha、サーバでは Expecto を利用する。 |
12-15 | バリデータが空の入力を弾くかテスト。 |