Haskellのdoctest入門


Haskellのdoctest入門


ソフトウェアを文書化することは挑戦的でありえます、しかし、それは必ずしもそうである必要はありません.
本稿では、DocTestを紹介します.
モジュールdocsの中にテストを置くことによって、doctestは関数が自分のために話すことを許します、そして、あなたがあなたのテスト努力から最も得るのを援助します.
記事を読む
  • doctestとは
  • Haskellでそれらを定義する方法
  • Haskell DocTestで使用するライブラリ.
  • doctestとは


    doctestは単にインタラクティブなセッションのようなドキュメントに埋め込まれたテキストの一部です.特別なライブラリを使用すると、これらのセッションを実行し、正しい値を返すことを確認できます.
    このアイデアは、Pythonの素晴らしいから来ている doctest モジュールが、その後、実質的にすべてのプログラミング言語に広がっている.
    Haskellでは、doctestはGHCIセッションですHaddock comments .
    もしあなたがHaskellのソースコードドキュメンテーションを通してスキムしなければならないなら、あなたはそれらの線が空想で気づいたかもしれません>>> 最初のシンボル.
    -- | @const x@ is a unary function which evaluates to @x@ for all inputs.
    --
    -- >>> const 42 "hello"
    -- 42
    --
    -- >>> map (const 42) [0..3]
    -- [42,42,42,42]
    
    
    推測したかもしれませんが、それらはdoctestです.

    Haskellでdoctestを定義する方法は?


    基本的なdoctestの例を見てみましょう.
    -- | 1 + 2 is 3.                          
    -- >>> 1 + 2                 
    -- 3
    
    
    ご覧のように、Haskellのdoctestには三つの要件があります.
  • すべてのdoctestの例は、有効なHaddock documentation , どちらによってマークされるか-- | or {- | .
  • すべてのdoctestの例は>>> そして、スコープにある有効なHaskell式を含んでいますimport ステートメント-私たちはさらに記事をカバーします.
  • すべてのdoctestの例には、式を評価する期待される結果を含む行が続きます.
  • あなたはDocTestのマークアップの追加情報を見つけることができますreadmedoctest 図書館.
    さて、DocTestを使用してプロジェクトを作成し、それらのdoctestを実行するために使用できるHaskellライブラリを調べましょう.

    DocTestを使用したHaskellプロジェクトの作成


    DocTestライブラリで動作するには、DocTestを使用したHaskellプロジェクトを作成する必要があります.
    まず、プロジェクトをブートストラップ stack :
    stack new doctests-demo
    
    
    その後、プロジェクトのルートディレクトリに移動し、Haskell module :
    cd doctests-demo
    
    
    touch src/Sample.hs
    
    
    最後に、doctestを使って新しく作成した関数を追加しますSample.hs モジュール
    -- src/Sample.hs
    
    module Sample where
    
    -- |
    -- >>> foo + 13
    -- 55
    foo :: Integer
    foo = 42
    
    -- |
    -- >>> bar
    -- "bar"
    bar :: String
    bar = "bar"
    
    
    プロジェクトは現在、doctestを実行する準備が整いました.

    Haskellのdoctestライブラリ


    Haskell生態系の2つのDocTestライブラリをカバーします. doctest and cabal-docspec . 最初のものは古くて、より人気がありますdoctest ’問題点.

    doctest


    doctest 最も一般的に使用され、積極的に維持されたdoctestライブラリの一つです.同時に、大規模プロジェクトやライブラリとしてGHC依存性のような欠点がある.

    doctestの使い方


    まず、ライブラリをインストールするstack :
    stack install doctest
    
    
    その後、プロジェクトのルートディレクトリに移動し、ライブラリの実行可能ファイルを使用します.
    cd doctests-demo
    
    
    doctest src
    
    
    上記のコマンドは次のように出力します.
    Examples: 2 Tried: 2 Errors: 0 Failures: 0
    
    

    doctestを使う


    ソフトウェアの素晴らしい部分ですが、ライブラリにはいくつかの欠点があります.
    最大の欠点は、ライブラリが大規模プロジェクトのためにあまりに遅いようです.パフォーマンスの問題を引き起こす理由の1つは、ライブラリがdoctestの各グループ間のソースを再読み込みすることです.これは、お互いに影響を与える例のグループを避けるために行われます.このことについてはlibrary’s readme .
    また、いくつかのマイナーな欠点があります.
    まず、依存性がGHC as a library , これは、プロジェクトを新しいコンパイラバージョンに切り替えると、結局何かが壊れてしまう可能性が高いということです.
    第二に stack , プロジェクト依存関係をスコープにするには、追加のテストスイートを作成する必要があります.

    依存性の低下のイラスト。


    私たちのdoctestの例を少し編集することでこれを説明しましょうaeson and text 依存関係の一覧には)
    -- src/Sample.hs
    
    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE TemplateHaskell #-}
    
    module Sample where
    
    import Data.Aeson
    import Data.Aeson.TH
    import Data.Text
    
    data Anime =
        Anime { title :: Text
              , rating :: Double
              }
    
    $(deriveJSON defaultOptions ''Anime)
    
    -- |
    -- >>> encode favourite
    -- "{\"title\":\"One-Punch Man\",\"rating\":8.9}"
    --
    favourite :: Anime
    favourite = Anime "One-Punch Man" 8.9
    
    
    さて、もし私たちがdoctestを実行しようとするならdoctest src , 次のメッセージで失敗します.
    src/Sample.hs:9:1: error:
        Could not find module ‘Data.Aeson’
        Perhaps you meant Data.Version (from base-4.14.3.0)
        Use -v (or `:set -v` in ghci) to see a list of the files searched for.
        |
    9 | import Data.Aeson
        | ^^^^^^^^^^^^^^^^^
    
    
    回避策は、追加のテストスイートを作成することです.
    tests:
    
        doctests:
        source-dirs: doctests
        main: Main.hs
        ghc-options:
            - -threaded
            - -rtsopts
            - -with-rtsopts=-N
        dependencies:
            - doctest
            # bring in your project into the scope
            # as well as its dependencies
            - doctests-demo
    
    
    その後、テストスイートディレクトリとMain.hs 実行可能
    mkdir doctests
    
    
    touch doctests/Main.hs
    
    
    -- doctests/Main.hs
    
    import Test.DocTest
    
    -- This test suite exists only to add dependencies
    main :: IO ()
    main = doctest ["src"]
    
    
    最後に、以下のコマンドを使ってdoctestを実行します.
    stack test :doctests
    
    

    カバル博士


    cabal-docspec 貢献者が少なく、全体的なコミュニティの注意が少ないが、人々の束はすでに実際のプロジェクトでそれを使用します.

    Caval docspecの使い方


    使いましょうcabal-docspec doctestを実行するにはdoctests-demo プロジェクト
    まず、セットアップcabal-install とグローバルコンパイラ.私たちはghcup これを達成する.
    その後、CACALでプロジェクトを構築します
    cabal v2-build
    
    
    ダウンロードcabal-docspec からのバイナリrelease page :
    curl -sL https://github.com/phadej/cabal-extras/releases/download/cabal-docspec-0.0.0.20211114/cabal-docspec-0.0.0.20211114.xz > cabal-docspec.xz
    xz -d < cabal-docspec.xz > "$HOME"/.local/bin/cabal-docspec
    rm -f cabal-docspec.xz
    chmod a+x "$HOME"/.local/bin/cabal-docspec
    
    
    ここで、doctestの例を実行します.
    cabal-docspec
    
    
    上記のコマンドは次のエラーに失敗します.
    expected: "{\"title\":\"One-Punch Man\",\"rating\":8.9}"
    but got:
                ^
                <interactive>:10:1: error:
                    Variable not in scope: encode :: Anime -> t
    
    
    ライブラリが少し違ったものを扱うので、上記のことが起こります.モジュールを明示的にインポート/エクスポートする必要があります.
    私たちのdoctestを少し編集しましょうcabal-docspec 仕事
     -- |
    + -- >>> import Data.Aeson
     -- >>> encode favourite
     -- "{\"title\":\"One-Punch Man\",\"rating\":8.9}"
     --
     favourite :: Anime
     favourite = Anime "One-Punch Man" 8.9
    
    
    現在cabal-docspec コマンドが成功する
    Total: 2; Tried: 2; Skipped: 0; Success: 2; Errors: 0; Failures 0
    Examples: 2; Tried: 2; Skipped: 0; Success: 2; Errors: 0; Failures 0
    
    

    なぜcabal docspecを使うべきか


    ここでは理由を使用する理由がありますcabal-docspec プロジェクトについて
  • ライブラリは、コンパイルされたコードを使用するため、代替よりもはるかに高速です.
  • ライブラリとしてGHCに依存しないので、GHCのバージョンの変更にはるかに弾力的です.
  • ライブラリはDocTestを変更するだけでソースコードを再コンパイルする必要はありません.これは開発者のための追加の時間を節約し、ドキュメントを快適に書くことができます.
  • 上記のすべては、それを実行可能な選択肢以上にします.
    しかし、図書館は密接に結びついているようだ cabal-install それ以来cabal-install 生成メタデータplan.json ファイル.

    結論


    読書ありがとう!
    記事では、私たちはDocTestの概念を見て、Haskellでそれらを定義する方法を学びました、そして、私たちがそれらを確かめるのを助けることができる2つのライブラリの概要を与えました:doctest and cabal-docspec .
    このシリーズの次の部分では、私たちの構成と内部のcabal-docspec 詳しくは.更新を維持するには、以下のフォームを介してニュースレターを購読または購読してください.