/usr/lib/ruby/vendor_ruby/functional_test_matrix.rb is in ruby-zentest 4.11.0-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | ########################################################################
# The Idea:
#
# This is supposed to get us thinking about the various dimensions our
# testing should address. If there are states orthogonal to each other
# (eg. readable vs unreadable, logged in vs not logged in) each of
# those states should comprise a dimension in the matrix. By
# addressing it this way, we should be able to minimize the amount of
# setup/teardown code and get full coverage across our actions for all
# these edge cases and as a result have extremely clear tests.
#
########################################################################
# Example Test Matrix Specification:
#
# matrix :example, :edge1, :edge2, :edge3, ...
# action :action1, :OK, :e_NF, :mod, ...
# action :action2, :OK, :e_RO, :na, ...
# action ...
#
########################################################################
# Matrix:
#
# I envision the setups being a code that combines the different
# dimensions of edge case state.
#
# Something for a CMS might look like: `[df]_[ugo]_[rRwW]` where:
#
# + `[df]` for dir/file.
# + and the rest is in the style of symbolic args to chmod:
# + u/g/o = user, group, or other
# + lowercase `X` == `X`able, uppercase `X` == un`X`able, where `X`
# is read/write.
#
########################################################################
# Action:
#
# :new/:err/:del are just examples, they should have semantic info
# attached to them.
#
# Use :na to specify an inapplicable edge case for that action.
#
# Use :OK to specify the standard positive state. It is equivalent to
# a result with the same name as the action. (eg
# matrix_test_index). This cleans up the matrix a lot and allows for
# narrower and more readable columns.
#
# Edge cases specific to an action that fall outside the matrix are
# regular tests.
#
########################################################################
# Matrix Methods (the legos):
#
# Everything else basically equates to lego pieces:
#
# + There is one "init" method per matrix: matrix_init_#{descr}(setup_args)
# + There is one "setup" method per action: matrix_setup_#{action}(setup, expect)
# + There is one "test" method per result: matrix_test_#{result}(setup)
#
# Thus, for the matrix "example" above, the top left-most test will
# end up calling:
#
# matrix_init_example(:edge1)
# matrix_setup_action1(:edge1, :new)
# matrix_test_new(:edge1)
#
# Read the action method for exact details.
########################################################################
module FunctionalTestMatrix
def matrix(name, *setups)
@@matrix, @@setups = name, setups
end
def action(action, *results)
testcases = @@setups.zip(results).reject { |a,b| b == :na }
testcases = Hash[*testcases.flatten]
matrix = @@matrix # bind to local scope for define_method closure
testcases.each do |setup, expected|
expected_action = expected == :OK ? action : expected
define_method "test_#{matrix}_#{action}_#{setup}" do
@action = action
send "matrix_init_#{matrix}", *setup.to_s.split(/_/).map {|c| c.intern }
send "matrix_setup_#{action}", setup, expected
send "matrix_test_#{expected_action}", setup
end
end
end
module_function :matrix, :action
end
|