2016-12-08 23 views
6

Test için Haskell WebDriver selenyum paketi aracılığıyla çalışıyorum, here.Bir haskell "withSubprocess" bir blok blogu etrafında inşa

Bu örnek var:

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 selenyum istemci Çalışıyorsa olmadan

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

ile iletişim kurmak için bir selenyum sunucusu gerektirdiği anlaşılır kılmakta bunu elde

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

Tüm test komut dosyamı t'yi başlatan bir işleve sarmak istiyorum O selenyum-sunucu, pidini kaydeder ve oturumu çalıştırdıktan sonra (pid) öldürür. Yani, mevcut ana sürem boyunca, java selenium-sunucusunu var olmaya çağırmak istiyorum, ancak çağrı biter bitmez mevcut olanı durdurmak istiyorum. , Id kayıt

python'da ben __enter__() ve diğer gözyaşı aşağı şeylerle bir __exit__(), subprocess.Popen tanımlayarak gibi bir şey bu do ediyorum, Öyle hissediyorum sonra

with Browser() as b: 
    do_stuff 

çağırarak, onu öldürmek runSession varlığı, bir argümanı olarak firefoxConfig $ do bloğunu alması ve bunu da yapmak istediğim için, bu şekilde başlatmayı ve teardown yapmayı kopyalamak için çoğaltmam gereken türden bir şeydir. Ben bunu ne kadar geçerli olabilir withMonad çeşit arıyor düşünüyorum

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

:

Ancak, ben oldukça runSession sorguya türlerini anlayamıyorum, nasıl bu tür şeyleri yapmaya do'a uygulanır. Bence sözdizimi bir çeşit ...

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            

Bunu nasıl başarabilirim? Monad hiç doğru mu? Bunun için daha fazla Haskell deyimi veya stratejisi var mı?

+1

A

withBrowser browserAction = bracket startSelenium killSelenium (const browserAction) 

Monad bir tür değil. Ayrıca, basit olsun. 'createProcess 've' runSession' her ikisi de 'IO'yu kullanır, yani' IO'da kalın. withBrowser :: IO a -> IO a'. – Zeta

+0

Neden kabuk komut dosyası kullanmıyorsunuz? – Ingo

cevap

1

Temel olarak bracket numaralı telefonu https://hackage.haskell.org/package/base-4.9.0.0/docs/Control-Exception.html#v:bracket'dan istiyorsunuz.

Üçüncü bir eylemin etrafından dolaşmak için IO eylemlerini ve kurulumunu belirtmenize izin verir. Kurulum eyleminin çıktısını otomatik olarak ana ve düşürme eylemlerine besler, kurulum işleminiz PID'yi sonuç olarak vermelidir, böylece gözyaşı eylemine PID'nin ne öldürmesi gerektiği söylenir.

şey gibi: (Sana pid için bir argüman almak zorunda ana eylem istemiyoruz varsaydım, bu yüzden görmezden const kullanılır)

+0

Argümden kaçınmak için bu bracket_ mı? – Mittenchops

+1

@Mittenchops Başlangıçta bunun istediğini de düşündüm, ama temizleme eyleminin de burada bir argümanı olmadığını unutmayın. Bu yüzden PID'yi başlatma eyleminden temizlik ürününe (IORef'e veya başka bir şeye yapıştırmadan) taşımak için bir yolunuz olmazdı. – Ben