Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Parallel testing world

Parallel testing world

by Shota Fukumori at the RubyConf2011 second day, 14:10-

Sorah Fukumori

October 02, 2011
Tweet

More Decks by Sorah Fukumori

Other Decks in Technology

Transcript

  1. DISCLAIMER • I’ll talk about parallel testing. • My English

    skill is unknown. • If you want to listen to general news around ruby 1.9.3, I strongly recommend you to move to Room 2. • Room 2 14:10: “Implementation of Ruby 1.9.3 and later” by ko1
  2. I missed a schedule of talking at RubyKaigi • 15

    minutes left when I ended a talk
  3. I missed a preparing schedule today • I finished writing

    today’s presentation file yesterday’s night (10pm).
  4. Agenda • Why Parallel Testing • Multi-Thread or Multi-Process •

    test/unit parallelization • How it works • Performance
  5. Agenda • Why Parallel Testing • Multi-Thread or Multi-Process •

    test/unit parallelization • How it works • Performance
  6. Benefits • In most case, tests can run more faster

    • Faster test → Fast development cycle • In TDD, BDD development • At Ruby, committers have to run `make test-all` before commit to repository. • Faster test make developers happy :-)
  7. lol

  8. :(

  9. Benefits • Q. You should run only few tests (like

    around the fixed point) at once. • A. Some changes make some failures at another point. In ruby, running all test at each commits is recommended.
  10. Example • rake cookpad:spec:remote • 4 servers: • Core i7

    (8 threads) + 16GB RAM + SSD • = 32 threads (!)
  11. Example • rake cookpad:spec:remote • Send local code to remote

    servers for running test with `rsync` • Run test via ssh. Outputs will be merged
  12. Why parallel testing • Modern machines have a multi (core|

    thread) • Use multi (core|thread) is the easiest way to run test faster!
  13. Agenda • Why Parallel Testing • Multi-Thread or Multi-Process •

    test/unit parallelization • How it works • Performance
  14. Multi-(thread|process) • Currently Ruby’s `Thread` doesn’t run parallel. • So,

    running multiple tests using `Thread` class in Ruby doesn’t make sense.
  15. Multi-`Thread` ? • Ruby’s Thread can’t run multiple threads at

    once... Time Thread 1 Thread 2 Thread 3 ŋŋŋ Running Thread
  16. Multi-Process ? • Multi process is good parallelization method at

    ruby. Time Test 2 Test 1 ŋŋŋ Core A Core B Test 1 Other 1 Other 2 Test 2 ↓Running process on each core Other: other process Test: testing process
  17. Agenda • Why Parallel Testing • Multi-Thread or Multi-Process •

    test/unit parallelization • How it works • Performance
  18. What’s test/unit • Unit testing library that shipped with Ruby

    • Before 1.9: test/unit doesn’t have any dependencies • After 1.9: test/unit is wrapper of minitest because of compatibility. • test/unit is used for Ruby’s unit testing.
  19. test/unit parallelization • I wrote a patch that allows test/unit

    runs multiple tests at once • Because I wanted to make Ruby’s `make test-all` (make target to test ruby) more more faster! :p • Fast is important™
  20. How it works • I’ll use the following words to

    describe how it works: • Master: a process that is started first. This Process sends a instruction to workers. • Example: a ruby process that started by `make test-all` • Worker: a process that is started by Master process. This process runs tests.
  21. How it works 1. Start master process (by like `make

    test- all`) 2. Master process starts worker processes 3. Master process sends a test file names to worker processes 4. Worker processes read a file that named passed by master process
  22. How it works 5. Worker processes run a test. 6.

    Worker processes return a test result to master process. 7. Master process send another test file name to worker process 8. Do from step 4 again.
  23. How it works • this feature uses stdin/stdout for communication

    between worker process and master process. • and this feature parallelize each test file. • so you have to separate tests and TestCase if you use this feature.
  24. How it works • User starts master process Master Test

    files test_a.rb test_b.rb test_c.rb
  25. How it works • Master process starts worker processes using

    IO.popen Master Worker Worker Test files test_a.rb test_b.rb test_c.rb IO.popen
  26. How it works • Master process sends file names of

    tests to worker process Master Worker Worker Test files test_a.rb test_b.rb test_c.rb test_a.rb test_b.rb
  27. How it works • Worker process reads test file from

    file system. Master Worker Worker Test files test_a.rb test_b.rb test_c.rb
  28. How it works • Worker process runs test Master Worker

    Worker Test files test_c.rb result result
  29. How it works • Worker process sends result to Master

    process. master saves results from workers. Master Worker Worker Test files test_c.rb result result
  30. How it works • Master sends remaining test file name.

    Master Worker Worker Test files test_c.rb result result test_c.rb
  31. How it works • Worker process runs next test Master

    Worker Worker Test files test_c.rb result result
  32. How it works • If there are no remaining test

    files, send quit instruction to worker Master Worker Worker Test files result result result Quit
  33. How it works • If there are no remaining test

    files, send quit instruction to worker Master Worker Worker Test files result result result Bye
  34. How it works • If there are no remaining test

    files, send quit instruction to worker Master Test files result result result
  35. How it works • If there are any results that

    contains more than one failure, master will retry in default Master result result result I have a failure!
  36. How it works • If there are any results that

    contains more than one failure, it’ll retry by master process in default Master result result test_b.rb Retry
  37. How it works • If there are any results that

    contains more than one failure, it’ll retry by master process in default Master result result result There are no failures.
  38. How it works • Because some tests fail because of

    parallelization. Master result result result There are no failures.
  39. How it works • Then merge the results and show

    to user Master result result result User via STDOUT
  40. In Ruby • some tests don’t consider a parallelization •

    it can guess (I guessed that) • The issues is: • Tests around network are using same port • Tests are using same directory
  41. test_signal.rb • test around signal handling of ruby. • this

    test run Kernel#fork to check fork is implemented. • test/unit’s at_exit called each fork. • I fixed test/unit to make be runnable this test. • Patch description: Add a flag to test/unit and interrupt if a flag is true in at_exit.
  42. test_process.rb • This test modifies STDIN/OUT. • this feature uses

    STDIN/OUT, so I modified to duplicate STDIN/OUT before run test in worker process.
  43. test_{http,https}.rb • These tests use same port number in test.

    • I fixed port number; but a fix is committed before I commit by Yui (nurse).
  44. test/csv/* • Tests included in this directory use same temporally

    directory name • All testcases use same directory name and they deletes temporaly directory in `teardown` phase. • So...
  45. test/rubygems/* • Recently they forget writing dependencies of test. •

    It makes problem at parallel_test. • because... ok, let’s show a example. Note: “dependency” is a file should be required.
  46. test/rubygems/* • if there are test_a.rb, test_b.rb, and foo.rb. •

    also test_a.rb and test_b.rb depends on foo.rb. • test_a.rb includes `require ‘foo’`, •but test_b.rb doesn’t.
  47. test/rubygems/* • When not using parallel testing: Time test_a.rb test_b.rb

    Running Test foo.rb is required. no errors. require ‘foo’
  48. test/rubygems/* • When parallel testing: Time test_a.rb test_b.rb Running Tests

    require ‘foo’ Ugh, foo.rb is not required... Exception ocucred...
  49. test/rubygems/* • I’m fixing that if I found. • This

    case can be found in any tests, but I founded only in the rubygems test. • I don’t know why. :p
  50. Agenda • Why Parallel Testing • Multi-Thread or Multi-Process •

    test/unit parallelization • How it works • Performance
  51. Performance • Kenta Murata a.k.a. @mrkn measured and created a

    performance graphs for me. • He’ll talk at the last session of room 2, about the ruby’s number system. • Thanks!
  52. Performance • Measured at the following environment: • OS: Mac

    OS X 10.6.6 • CPU: Intel Core i7 2.66 GHz • (2 cores 4 threads) • Memory: 8GB 1067 MHz DDR3 • Test files is from ruby’s repository
  53. Performance 0 32.5 65.0 97.5 130.0 single 1 2 3

    5 8 13 Elapsed time Seconds worker(s)
  54. Performance • Without parallelization (“no -j”): 121.49 seconds • Enabled

    parallelization with 5 workers: 43.41 seconds 2.79x Faster!
  55. How to use • Separate TestCase-s to multiple file. •

    Write script to run multiple test file using Test::Unit::AutoRunner. • good example is ruby’s test/runner.rb in ruby’s repository. • Run the script with argument -j N. • Running the script with --help provides more information.
  56. Announcement • Ruby 1.9.3 RC1 has been released! • You

    can use parallelization by installing this! • Let’s try it and tell us if you found a bug. • More about: http://www.ruby-lang.org/
  57. Any Questions? If I can’t answer to your question because

    of my English skill, please send tweet to @sora_h or mail me: [email protected].