the sour cream into the mixing bowl. Put the white sugar into the mixing bowl. Put the yogrut into the mixing bowl. Put the unsalted butter into the mixing bowl. Combine the milk. Put the cake flour into the mixing bowl. Combine the corn starch. Put the brown sugar into the mixing bowl. Combine the egg whites. Combine the egg yolks. Put the lemon juice into the mixing bowl. Stir for 7 minutes. Liquify the contents of the mixing bowl. Pour contents of the mixing bowl into the baking dish Bake the cake mixture. Watch the cake mixture until baked. Serves 4. Cheese cake in Chef. Ingredients. 100 g cream cheese 97 g sour cream 107 g yogrut 112 g white sugar 11 g brown sugar 37 g unsalted butter 37 g cake flour 3 g corn starch 3 ml milk 3 egg yolks 3 egg whites 10 ml lemon juice 0 g cake mixture Cooking time: 80 minutes. ‘d’ ‘a’ ‘k’ ‘p’ 11*3*3=99 ‘c’ 37*3=111 ‘o’ ¥n ‘o’ Push characters ‘¥n’ ‘d’ ‘a’ ‘p’ ‘k’ ‘o’ ‘o’ ‘c’ into the stack Convert them to a string and “serve” it. data code
keyword arguments, deadlock detection, etc. • Release management for Ruby 1.9.2 and 2.0.0 • Optcarrot: A NES emulator for Ruby3x3 benchmark • Enhancement of the test suite of Ruby • coverage.so: the core library for coverage measurement ’06B ’07A ’07B ’08A 60 70 80 90 100 coverage (%) 70% 85% line coverage
test suite – Also called “test coverage” or “code coverage” • Allows you: – Find untested code – Decide whether your test suite is good enough or not yet • (This is arguable, but I think we can use it as an advice) • Types of coverage – Function coverage, line coverage, branch coverage, …
tests # code def foo; …; end # ✓ def bar; …; end # ✗ def baz; …; end # ✓ # test foo baz 2/3 (67%) • Advantage • Easy to understand • Easy to visualize • Disadvantage • Too weak as a measure
def foo(x) # ✓ if x == 0 # ✓ p :foo # ✗ else p :bar # ✓ end end # test foo(1) 3/4 (75%) Non-significant line is ignored • Advantage • Easy to understand • Easy to visualize • Disadvantage • Still weak as a measure • foo() if x == 0
false # code def foo(x) p :foo if x == 0 # ✓ p :bar if x < 2 # ✗ end # test foo(0) foo(1) 1/2 (50%) • Advantage • Relatively exhaustive • Disadvantage • Difficult to visualize true-case and false-case are both executed
conditions (not branches) are taken both true and false • Path coverage – How many paths are executed – Combinatorial explosion • Other advanced ones – Data-flow coverage – MC/DC coverage if a && b branch condition condition
A test is the only way to ensure quality – Coverage is important to measure test goodness • Considering it, coverage is not used so much… – Coverage is not well-known? – It is not well-known how to use coverage? – Ruby’s coverage measurement feature is not enough? • I’d like to improve the situation with this talk
will 1. Pick untested code that looks easiest to cover 2. Write a trivial test just for the code 3. Iterate this procedure until XX% is achieved • It will result in trivial, not-so-good test suite – It may be exhaustive for the code itself, but – It won't be exhaustive for the design
Look at untested code 2. Consider what “test design” is insufficient 3. Write them – In consequence of them, the untested code is executed • It will result in good test suite – It will be exhaustive not only for the code but also for the design
module being tested – Aim 100% for a significant module (e.g., injure someone) – Don't worry too much for a non-significant module • It also depends upon cost performance – For non-significant module, write a test only if it is not so hard • Again: Coverage is not a goal
test/test_helper.rb • Run the test suite • coverage/index.html will be produced – Note: SimpleCov cannot measure already- loaded files before SimpleCov.start require "simplecov" SimpleCov.start
Coverage.result #=> {"target.rb"=> # [nil,nil,1,1,1,nil, # 0,nil,nil,nil,1]} Start measuring coverage Load the target file Stop measuring and get the result Coverage data
coverage • Excuse: I introduced it just for test enhancement of Ruby itself – I didn't deliberate the API for external project… • I have wanted to make the next version better ext/coverage/coverage.c: 69 /* Coverage provides coverage measurement feature for Ruby. 70 * This feature is experimental, so these APIs may be changed in future. 71 *
coverage • Developed for monitoring Ruby's coverage • Author: me • Presented at RubyKaigi 2009, and then… – It has not been used by everyone (including me) – It was based on Ramaze (old web framework)!
with gcc: gcc -coverage target.c • Java: A lot of tools – Cobertura, Emma, Clover, JaCoCo – Integrated with CI tools and/or IDEs • JavaScript: Istanbul Jenkins Cobertura plugin LCOV result
coverage – There have been multiple requests and some PoC patches… • To make the API better, any comments are welcome – https://bugs.ruby-lang.org/issues/13901
[:then, 1, 3]=>2, [:else, 2, 5]=>1 } }, :methods=>{ [:test_if, 1]=>3 }}} # target1.rb 1: def test_if(x) 2: if x == 0 3: p "x == 0" 4: else 5: p "x != 0" 6: end 7: end 8: 9: test_if(0) 10: test_if(0) 11: test_if(1) From if at Line 2 Jumped to then clause at Line 3 twice Jumped to else clause at Line 5 once
<line-no>] – e.g., [:if, 0, 1], [:while, 1, 1], [:case, 2, 1] – <numbering> is a unique ID to avoid conflicts for the case where there are multiple branches in one line • LCOV-style – Other candidates: • [<label>, <line-no>, <column-no>] – How to handle TAB character • [<label>, <offset from file head>] – Looks good, but hard to implement (I'll try later)
with C code coverage by GCOV and Visualized by LCOV Ruby code in stdlib make exam with gcc -coverage make exam COVERAGE=1 test- coverage .dat *.gcda gcov my script run test C code of MRI cov. data source aggregate lcov HTML
how to understand coverage • The current status of Ruby's coverage measurement and ecosystem • A plan towards Ruby 2.5 and preliminary demo – Any comments are welcome! – https://bugs.ruby-lang.org/issues/13901