Skip to content

Instantly share code, notes, and snippets.

@asufana
Created December 29, 2015 12:29
Show Gist options
  • Save asufana/31189bcd1277d6bbadf8 to your computer and use it in GitHub Desktop.
Save asufana/31189bcd1277d6bbadf8 to your computer and use it in GitHub Desktop.
OSX での F# (FSharp) プロジェクト管理

OSX での F# (FSharp) プロジェクト管理

環境情報

  • OSX El Capitan 10.11.1
  • mono 4.2.1

以下で paket、FAKE 環境を整備しておく

Yeoman インストール

FSharpプロジェクトフォルダの雛形を作成するために Yeoman を導入する

node.js インストール
$ brew install node
Yeoman インストール

Yeoman と generator-fsharp をインストール

$ npm install -g yo
$ npm install -g generator-fsharp

ソリューションフォルダ作成

$ yo fsharp
? What do You want to do? => Create empty solution
? What's the name of your application? => Sample
? Do You want to use Paket? => Yes
$ tree Sample
Sample/
├── Sample.sln
├── packages
├── paket.dependencies
└── paket.lock

sln ファイルを利用しない方法もあり

アプリケーション・プロジェクト作成

$ cd Sample
$ yo fsharp
? What do You want to do? => Add new project to solution
? What type of application do you want to create? => Class Library
? What's the name of your application? => SampleApp
? Do You want to use Paket? => Yes
$ tree SampleApp/
SampleApp/
├── SampleApp.fs
├── SampleApp.fsproj
└── Script.fsx
$ cat SampleApp.fs
namespace SampleApp

type SampleApp() =
    member this.X = "F#"
ビルド
$ /usr/local/bin/xbuild SampleApp.fsproj
...
Build succeeded.
	 0 Warning(s)
	 0 Error(s)
$ tree
.
├── SampleApp.fs
├── SampleApp.fsproj
├── Script.fsx
├── bin
│   └── Debug
│       ├── FSharp.Core.dll
│       ├── SampleApp.XML
│       ├── SampleApp.dll
│       └── SampleApp.dll.mdb
└── obj
    └── Debug
        ├── SampleApp.dll
        ├── SampleApp.dll.mdb
        └── SampleApp.fsproj.FilesWrittenAbsolute.txt

テスト・プロジェクト作成

$ cd Sample
$ yo fsharp
? What do You want to do? => Add new project to solution
? What type of application do you want to create? => Class Library
? What's the name of your application? => SampleTest
? Do You want to use Paket? => Yes
ライブラリ追加
$ cd SampleTest
$ paket init
$ vim paket.dependencies
source https://www.nuget.org/api/v2
nuget Nunit
nuget FsUnit

$ paket install
ファイル拡張子変更
$ mv SampleTest.fs SampleTest.fsx
$ vim SampleTest.fsproj
...
<ItemGroup>
    <Compile Include="SampleTest.fsx" />
...
SampleTest.fsx 修正

SampleApp.fs のオブジェクトを呼び出すコードを記述

$ vim SampleTest.fsx
#!/usr/bin/env fsharpi

#r "packages/NUnit/lib/nunit.framework.dll"
#r "packages/FsUnit/lib/net45/NHamcrest.dll"
#r "packages/FsUnit/lib/net45/FsUnit.NUnit.dll"
open NUnit.Framework
open FsUnit

#load "../SampleApp/SampleApp.fs"
open SampleApp

let sampleApp = new SampleApp()
printfn "SampleApp.X is %s." sampleApp.X

実行してみる

$ chmod 777 SampleTest.fsx
$ ./SampleTest.fsx
SampleApp.X is F#.
単体テストコードを追記
$ vim SampleTest.fsx
#!/usr/bin/env fsharpi

#r "packages/NUnit/lib/nunit.framework.dll"
#r "packages/FsUnit/lib/net45/NHamcrest.dll"
#r "packages/FsUnit/lib/net45/FsUnit.NUnit.dll"
open NUnit.Framework
open FsUnit

#load "../SampleApp/SampleApp.fs"
open SampleApp

let sampleApp = new SampleApp()
printfn "SampleApp.X is %s." sampleApp.X

[<TestFixture>]
type ``test sampleApp`` ()=
  let sampleApp = new SampleApp()

  [<Test>] member x.
    ``prop X test`` () =
      sampleApp.X |> should equal "C#"
プロジェクトをビルド
$ /usr/local/bin/xbuild SampleTest.fsproj
...
Build succeeded.
	 0 Warning(s)
	 0 Error(s)
テストを実行
$ cd bin/Debug
$ cp ../../packages/NUnit/lib/nunit.framework.dll .
$ cp ../../packages/FsUnit/lib/net45/FsUnit.NUnit.dll .

$ /usr/local/bin/nunit-console SampleTest.dll
...
Tests run: 1, Failures: 0, Not run: 0, Time: 0.050 seconds

参考 http://stackoverflow.com/questions/30736006/how-to-launch-fsunit-tests-on-linux-mac

ビルドからテストを自動化する

FAKE をインストール
$ cd Sample
$ vim paket.dependencies
source https://www.nuget.org/api/v2
nuget FAKE

$ paket install
ビルドスクリプトを用意
$ cd Sample
$ touch build.fsx
$ vim build.fsx
#r "packages/FAKE/tools/FakeLib.dll"
open Fake

RestorePackages()

// Properties
let buildDir = "./build/"
let testDir  = "./test/"

// Targets
Target "Clean" (fun _ ->
  CleanDirs [buildDir; testDir]
  CopyFile testDir ("SampleTest/packages/FsUnit/lib/net45/FsUnit.NUnit.dll")
  CopyFile testDir ("SampleTest/packages/NUnit/lib/nunit.framework.dll")
)

Target "BuildApp" (fun _ ->
 !! "SampleApp/**/*.fsproj"
   |> MSBuildRelease buildDir "Build"
   |> Log "AppBuild-Output: "
)

Target "BuildTest" (fun _ ->
  !! "SampleTest/**/*.fsproj"
    |> MSBuildDebug testDir "Build"
    |> Log "TestBuild-Output: "
)

Target "Test" (fun _ ->
  !! (testDir + "/*Test.dll")
    |> NUnit (fun p ->
      {p with
        //http://fsharp.github.io/FAKE/apidocs/fake-nunitcommon-nunitparams.html
        DisableShadowCopy = true;
        ToolPath = "/usr/local/bin";
        ToolName = "nunit-console";
        OutputFile = buildDir + "TestResults.xml";
        ErrorOutputFile = buildDir + "TestErrors.xml" })
)

Target "Default" (fun _ ->
  trace "Hello World from FAKE"
)

// Dependencies
"Clean"
  ==> "BuildApp"
  ==> "BuildTest"
  ==> "Test"
  ==> "Default"

// start build
RunTargetOrDefault "Default"

参考 http://fsharp.github.io/FAKE/gettingstarted.html

ビルドスクリプトを実行する
$ fakerun build.fsx
...
---------------------------------------------------------------------
Build Time Report
---------------------------------------------------------------------
Target      Duration
------      --------
Clean       00:00:00.0116677
BuildApp    00:00:04.3932624
BuildTest   00:00:00.8806620
Test        00:00:01.0196884
Default     00:00:00.0001113
Total:      00:00:06.3335030
Status:     Ok
---------------------------------------------------------------------

...

fakerun コマンドはこちらを参考 https://gist.github.com/asufana/b64f280fe5e442a45253

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment