Skip to content

Instantly share code, notes, and snippets.

@tmhedberg
Created March 6, 2013 03:58
Show Gist options
  • Select an option

  • Save tmhedberg/5096581 to your computer and use it in GitHub Desktop.

Select an option

Save tmhedberg/5096581 to your computer and use it in GitHub Desktop.
Parallel RSpec test runner
#!/usr/bin/runhaskell
import Control.Category ((>>>))
import Data.Function
import Data.Functor
import Data.List
import System.Environment
import System.Info
import System.IO
import System.Process
main = do
examples <- parseRSpecList <$> getRSpecList
numCores <- getNumCores
mapM (uncurry runSpecs) (zip (numCores `groups` examples) [1..]) >>=
mapM_ waitForProcess
getRSpecList :: IO String
getRSpecList = readProcess "rails" ["runner", "spec_fail.rb"] ""
parseRSpecList :: String -> [String]
parseRSpecList = lines
>>> dropWhile (/="Failed examples:")
>>> drop 2
>>> takeWhile (isPrefixOf "rspec")
>>> map trimExample
trimExample :: String -> String
trimExample = init . takeWhile (/='#') . drop 6
getNumCores :: IO Int
getNumCores
| "linux" <- os = length . filter (isPrefixOf "processor") . lines
<$> readFile "/proc/cpuinfo"
| "darwin" <- os = read <$> readProcess "sysctl" ["-n", "hw.ncpu"] ""
| otherwise = hPutStrLn stderr "Sorry, I don't know how many cores you have!"
>> return 1
runSpecs :: [String] -> Int -> IO ProcessHandle
runSpecs examples testEnv = do
env <- getEnvironment
runProcess "rspec"
examples
Nothing
(Just $ ("TEST_ENV_NUMBER", show testEnv):env)
Nothing
Nothing
Nothing
groups :: Int -> [a] -> [[a]]
n `groups` xs = groups' xs
where
groups' xs
| length xs <= groupLen = [xs]
| otherwise = let (pre, rest) = splitAt groupLen xs in pre : groups' rest
groupLen = ceiling $ ((/) `on` fromIntegral) (length xs) n
RSpec.configure { |config| config.before(:all) { raise nil } }
RSpec::Core::Runner.run %w[--no-color spec]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment