2016-12-08 4 views
6

私はテストのためにHaskell WebDriver seleniumパッケージhereを使って作業しています。doブロックのhaskell "withSubprocess"コンストラクション

私はこの例があります。

import Test.WebDriver 

firefoxConfig :: WDConfig 
firefoxConfig = defaultConfig 

main :: IO() 
main = runSession firefoxConfig $ do      
    openPage "http://google.com"        
    searchInput <- findElem (ByCSS "input[type='text']") 
    sendKeys "Hello, World!" searchInput      
    submit searchInput          
    closeSession            

getting started sectionはセレンクライアントは、それが実行せずに

java -jar selenium-server-standalone-*.jar 

との通信にセレンサーバーが必要であることを明らかにし、あなたはこれを取得:

ghci λ> main 
*** Exception: FailedConnectionException2 "127.0.0.1" 4444 False connect: does not exist (Connection refused) 

私はtを初期化する関数で私のテストスクリプト全体をラップしたいと思います彼はセッションを実行した後、彼はselenium-server、pidを記録してkill(pid)します。つまり、私の既存のメインの期間、Java Selenium-Serverを呼び出すことを望みますが、呼び出しが終了するとすぐに既存のSeleniumサーバーを停止したいと思います。 Pythonで

私は、他のティアダウンのもので__enter__()__exit__()を定義するようなもので、これを行うsubprocess.Popen、IDを記録し、それを殺す、私は感覚を得る

with Browser() as b: 
    do_stuff 

を呼び出したいですrunSessionエンティティは、引数としてfirefoxConfig $ doブロックを受け取り、それをやりたいという意味で、スタートアップとティアダウンをラップするために複製する必要があるものです。

しかし、私はかなりこの種のものを作る方法を、runSessionを尋問からタイプを理解することはできません。

ghci λ> :t runSession 
runSession 
    :: Test.WebDriver.Config.WebDriverConfig conf => 
    conf -> WD a -> IO a 

私は私がこれに適用することができwithMonadのいくつかの種類を探していると思いますこれはdoに適用されます。私は構文がある種のものだと思う。

import Test.WebDriver 
import System.Process 

firefoxConfig :: WDConfig 
firefoxConfig = defaultConfig 

withBrowser :: Monad a -> Monad a -- maybe this type? 
withBrowser = do 
    r <- createProcess (proc "java -jar selenium-server-standalone-*.jar" []) 
    -- other magic here? 

main :: IO() 
main = withBrowser $ runSession firefoxConfig $ do      
    openPage "http://google.com"        
    searchInput <- findElem (ByCSS "input[type='text']") 
    sendKeys "Hello, World!" searchInput      
    submit searchInput          
    closeSession            

私はこれをどのように達成するだろうか?モナドはまったくですか?これ以上のハスケルのイディオムや戦略はありますか?

+1

Aを

withBrowser browserAction = bracket startSelenium killSelenium (const browserAction) 

'Monad'はタイプではありません。また、それを簡単に保つ。 'createProcess 'と' runSession'はどちらも 'IO'を使うので' IO'にとどまります。 'withBrowser :: IO a - > IO a'を実行します。 – Zeta

+0

なぜシェルスクリプトを使用しないのですか? – Ingo

答えて

1

bracketは、基本的にはhttps://hackage.haskell.org/package/base-4.9.0.0/docs/Control-Exception.html#v:bracketです。

設定とティアダウンのIOアクションを指定して、3番目のアクションを実行することができます。それは自動的にセットアップアクションの出力をメインとティアダウンアクションの両方に送りますが、セットアップアクションは結果としてPIDだけを与えるべきなので、ティアダウンアクションはどのPIDを殺すのかを知らされます。

何かのように:(私はあなたがPIDの引数を取るために持っている主なアクションをしたくないと仮定しましたので、私はそれを無視するconstを使用)

+0

そのブラケット_はargを避けるためのものですか? – Mittenchops

+1

@Mittenchops当初私はそれもあなたが望むだろうと思っていましたが、クリーンアップアクションには引数もありません。 PIDをスタートアップ・アクションからクリーンアップ・アクションに(IORefなどに固執せずに)転送する方法はありません。 – Ben

関連する問題