計算機科学のブログ

コードの整理とプロジェクトのビルド QuickCheckを使ったプロパティテスト QuickCheckによるプロパティテスト quickCheck関数、stack testコマンド

入門Haskellプログラミング (Will Kurt(著)、株式会社クイープ(監修、翻訳)、翔泳社)のUNIT6(コードの整理とプロジェクトのビルド)、LESSON 36(QuickCheckを使ったプロパティテスト)、36.3(QuickCheckによるプロパティテスト)、プロパティテストのクイックチェック 36-4、QuickCheckのクイックチェック 36-5の解答を求めてみる。

以前と同様、本著のようにpalindrome-testing.cabalファイルではなくpackage.yamlを変更する必要があるみたいだった。

palindrome-testing/package.yaml

name:                palindrome-testing
version:             0.1.0.0
github:              "githubuser/palindrome-testing"
license:             BSD3
author:              "Author name here"
maintainer:          "example@example.com"
copyright:           "2021 Author name here"

extra-source-files:
- README.md
- ChangeLog.md

# Metadata used when publishing your package
# synopsis:            Short description of your package
# category:            Web

# To avoid duplicated efforts in documentation and dealing with the
# complications of embedding Haddock markup inside cabal files, it is
# common to point users to the README.md file.
description:         Please see the README on GitHub at <https://github.com/githubuser/palindrome-testing#readme>

dependencies:
- base >= 4.7 && < 5

library:
  source-dirs: src

executables:
  palindrome-testing-exe:
    main:                Main.hs
    source-dirs:         app
    ghc-options:
    - -threaded
    - -rtsopts
    - -with-rtsopts=-N
    dependencies:
    - palindrome-testing

tests:
  palindrome-testing-test:
    main:                Spec.hs
    source-dirs:         test
    ghc-options:
    - -threaded
    - -rtsopts
    - -with-rtsopts=-N
    dependencies:
    - palindrome-testing
    - QuickCheck

コード

palindrome-testing/test/Spec.hs

import Test.QuickCheck
import Lib
import Data.Char(isPunctuation)

prop_punctuationInvariant text =
    let noPuncText = filter (not . isPunctuation) text
    in  preprocess text == preprocess noPuncText

-- クイックチェック 36-4
prop_reverseInvariant text =
    isPalindrome text == isPalindrome (reverse text)

-- assert :: Bool -> String -> String -> IO ()
-- assert test passStatement failStatement =
--     putStrLn (if test
--               then passStatement
--               else failStatement)

main :: IO ()
main = do
    -- putStrLn "Running tests..."
    -- -- せっかくだからmapM_関数を使用して本著のコードよりちょっと短く
    -- mapM_ (\word -> assert (isPalindrome word)
    --                        (mconcat ["passed '", word, "'"])
    --                        (mconcat ["FAIL: '", word, "'"]))
    --      ["racecar",
    --       "racecar!",
    --       "cat",
    --       ":racecar:"]
    quickCheck prop_punctuationInvariant
    quickCheck prop_reverseInvariant
    putStrLn "done!"

palindrome-testing/src/Lib.hs

-- 特定の関数ではなく全ての関数をエクスポートするために括弧による関数の指定を削除
module Lib( isPalindrome
          , preprocess) where

import Data.Char(isPunctuation)

preprocess :: String -> String
preprocess = filter (not . isPunctuation)

isPalindrome :: String -> Bool
isPalindrome text =
    let cleanText = filter (not . (== '!')) text
    in cleanText == reverse cleanText

入出力結果(Terminal, Zsh)

% stack test
palindrome-testing-0.1.0.0: unregistering (local file changes: test/Spec.hs)
palindrome-testing> build (lib + exe + test)
Preprocessing library for palindrome-testing-0.1.0.0..
Building library for palindrome-testing-0.1.0.0..
Preprocessing test suite 'palindrome-testing-test' for palindrome-testing-0.1.0.0..
Building test suite 'palindrome-testing-test' for palindrome-testing-0.1.0.0..
[2 of 2] Compiling Main
Linking .stack-work/dist/x86_64-osx/Cabal-3.2.1.0/build/palindrome-testing-test/palindrome-testing-test ...
Preprocessing executable 'palindrome-testing-exe' for palindrome-testing-0.1.0.0..
Building executable 'palindrome-testing-exe' for palindrome-testing-0.1.0.0..
palindrome-testing> copy/register
Installing library in /Users/kamimura/…/palindrome-testing/.stack-work/install/x86_64-osx/e67eb8948c5ca5b05145d327b42dbaf36b07cbc5c162184cfcce5372fdfb9a45/8.10.7/lib/x86_64-osx-ghc-8.10.7/palindrome-testing-0.1.0.0-D5gXyPE6TE83uzq62K2GmW
Installing executable palindrome-testing-exe in /Users/kamimura/…/palindrome-testing/.stack-work/install/x86_64-osx/e67eb8948c5ca5b05145d327b42dbaf36b07cbc5c162184cfcce5372fdfb9a45/8.10.7/bin
Registering library for palindrome-testing-0.1.0.0..
palindrome-testing> test (suite: palindrome-testing-test)
                                
+++ OK, passed 100 tests.
+++ OK, passed 100 tests.
done!

palindrome-testing> Test suite palindrome-testing-test passed
Completed 2 action(s).
%