callmekohei's blog

callmekoheiのひとりごと

F#を気軽にテスト〜・それVimで

Summary

F#のコードをVimで手軽にテストしてみた

こんな感じ

必要なもの

  • Neovim
  • deoplete-fsharp

テストの仕方

  • Persimmonをゲッツ(Nuget, Paketおこのみで)
  • テストコードを書く
  • :Persimmonコマンドを実行

いいところ

気軽にテストできるところ(Persimmonコマンドを入力するだけ)

残念なところ

結果が出るまでに3秒ほどかかること

ちょっとした解説

Persimmonコマンドは以下のように動作します

同じフォルダに`Persimmon.Console.exe`があるか?
↓
同じフォルダに`tools`フォルダがあるか?(あればそのなかに`Persimmon.Console.exe`があるか?)
↓
同じフォルダに`Packages`フォルダがあるか?(あればそのなかに`Persimmon.Console.exe`があるか?)
↓
上記で見つからなければ`deoplete-fsharp`の`Persimmon.Console.exe`を使う






tutorial 01

Persimmon を使った簡単なテスト

paketコマンドはこちらを参照

// 実験フォルダをつくる
$ mkdir jikken

// 実験フォルダに移動
$ cd jikken

// paketを初期化
$ paket init

// ダウンロードするファイルをかく
$ vim paket.dependencies 

***********************
*
*   source https://www.nuget.org/api/v2
*   nuget Persimmon.Console -OutputDirectory tools -ExcludeVersion
*
***********************

// ダウンロード
$ paket install

// テストコードをかく
$ vim test.fsx

code

#r "./packages/Persimmon.Console/tools/Persimmon.dll"
open Persimmon
open UseTestNameByReflection

let add   x y = x + y

let ``first test example`` = test {
    do! assertEquals 6 (add 1 5)
}

Persimmonコマンドを実行

: Persimmon

結果

.
============================== summary ===============================
run: 1, error: 0, violated: 0, skipped: 0, duration: 00:00:00.0934450


*** time : 3.035613 s ***


tutorial 02

tutorial 01 のつづき( jikken フォルダーにいるものとします)

依存のある`dll, exe`をサブフォルダにまとめる方法


dll, exeをまとめるlibフォルダをつくってPersimmonのサブフォルダにする

// libフォルダをつくる
$ mkdir lib

// コードをかく
$ vim ./lib/hello.fsx

code

namespace callmekohei

module Hello =

    let say (word:string) =
        word + " hello!"
// dllファイルを作成
$ fsharpc -a ./lib/hello.fsx

// libフォルダを Persimmon.Console.exe の下におく
$ mv  /lib packages/Persimmon.Console/tools/

ファイルの状況
jikken$ tree packages/
packages/
├── Paket
│   ├── Paket.nupkg
│   └── tools
│       └── paket.exe
└── Persimmon.Console
    ├── Persimmon.Console.2.0.1.nupkg
    ├── Persimmon.Console.nuspec
    ├── [Content_Types].xml
    ├── _rels
    ├── license.html
    ├── package
    │   └── services
    │       └── metadata
    │           └── core-properties
    │               └── coreProp.psmdcp
    └── tools
        ├── FSharp.Core.dll
        ├── Persimmon.Console.exe
        ├── Persimmon.Console.exe.config
        ├── Persimmon.Runner.dll
        ├── Persimmon.Runner.dll.config
        ├── Persimmon.dll
        ├── Persimmon.dll.config
        ├── System.ValueTuple.dll
        └── lib    <-------------------- sub foler!
            ├── hello.dll
            └── hello.fsx

10 directories, 17 files

設定ファイル(Persimmon.Console.exe.config)を書き直す

$ vim packages/Persimmon.Console/tools/Persimmon.Console.exe.config 

下記のようにかく(<probing privatePath="lib"/>を追加するだけ)

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      
      <!-- Look for addins in the addins directory for now -->
      <probing privatePath="lib"/> 
      
      <dependentAssembly>
        <assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.4.1.0" newVersion="4.4.1.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

テストファイルを作成する

// テストファイル test2.fsx を作成する
$ vim test2.fsx

code

#r "./packages/Persimmon.Console/tools/Persimmon.dll"
open Persimmon
open UseTestNameByReflection

#r "./packages/Persimmon.Console/tools/lib/hello.dll"
open callmekohei


let ``first test example`` = test {
    do! assertEquals "abc" ( Hello.say "hello" )
}

test実施(Persimmonコマンド実行)

: Persimmon

結果

x
begin Test2_deoplete-fsharp_temporary_file
Assertion Violated: first test example
1. Expect: "abc"
Actual: "hello hello!"
end Test2_deoplete-fsharp_temporary_file
============================== summary ===============================
run: 1, error: 0, violated: 1, skipped: 0, duration: 00:00:00.1194835


*** time : 2.941333 s ***

おまけ

超気軽なテスト

code

#r "./packages/Persimmon.Console/tools/Persimmon.dll"
open Persimmon

let add   x y = x + y

assertEquals 1 ( add 1 1)
|> printfn "%A"

:QUICKRUNfsを実行

NotPassed (None,Violated "Expect: 1
Actual: 2")


*** time : 0.072349 s ***

これならはやい!