assay 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/.ruby +46 -41
  2. data/COPYING.rdoc +38 -0
  3. data/HISTORY.rdoc +18 -1
  4. data/QED.rdoc +1100 -0
  5. data/README.rdoc +139 -16
  6. data/lib/assay.rb +82 -29
  7. data/lib/assay.yml +46 -41
  8. data/lib/assay/{adapters → adapter}/minitest.rb +0 -0
  9. data/lib/assay/{adapters → adapter}/testunit.rb +0 -0
  10. data/lib/assay/assertable.rb +174 -0
  11. data/lib/assay/assertion.rb +98 -124
  12. data/lib/assay/assertor.rb +187 -0
  13. data/lib/assay/boolean_assay.rb +15 -0
  14. data/lib/assay/case_assay.rb +17 -0
  15. data/lib/assay/compare_assay.rb +38 -0
  16. data/lib/assay/core_ext/kernel.rb +52 -0
  17. data/lib/assay/core_ext/na.rb +9 -0
  18. data/lib/assay/directory_assay.rb +20 -0
  19. data/lib/assay/empty_assay.rb +17 -0
  20. data/lib/assay/equal_assay.rb +35 -0
  21. data/lib/assay/equality_assay.rb +18 -0
  22. data/lib/assay/execution_assay.rb +59 -0
  23. data/lib/assay/false_assay.rb +17 -0
  24. data/lib/assay/file_assay.rb +17 -0
  25. data/lib/assay/identity_assay.rb +49 -0
  26. data/lib/assay/include_assay.rb +17 -0
  27. data/lib/assay/instance_assay.rb +17 -0
  28. data/lib/assay/kind_assay.rb +18 -0
  29. data/lib/assay/less_assay.rb +18 -0
  30. data/lib/assay/less_equal_assay.rb +25 -0
  31. data/lib/assay/like_assay.rb +17 -0
  32. data/lib/assay/match_assay.rb +17 -0
  33. data/lib/assay/more_assay.rb +18 -0
  34. data/lib/assay/more_equal_assay.rb +25 -0
  35. data/lib/assay/nil_assay.rb +15 -0
  36. data/lib/assay/nomatch_assay.rb +17 -0
  37. data/lib/assay/output_assay.rb +35 -0
  38. data/lib/assay/path_assay.rb +17 -0
  39. data/lib/assay/raise_assay.rb +109 -0
  40. data/lib/assay/rescue_assay.rb +55 -0
  41. data/lib/assay/respond_assay.rb +17 -0
  42. data/lib/assay/return_assay.rb +46 -0
  43. data/lib/assay/silent_assay.rb +59 -0
  44. data/lib/assay/stderr_assay.rb +30 -0
  45. data/lib/assay/stdout_assay.rb +30 -0
  46. data/lib/assay/throw_assay.rb +89 -0
  47. data/lib/assay/true_assay.rb +20 -0
  48. data/lib/assay/unequal_assay.rb +37 -0
  49. data/lib/assay/within_assay.rb +39 -0
  50. data/test/case_compare_assay.rb +59 -0
  51. data/test/case_empty_assay.rb +51 -0
  52. data/test/case_equal_assay.rb +53 -0
  53. data/test/case_equality_assay.rb +55 -0
  54. data/test/case_false_assay.rb +48 -0
  55. data/test/case_identity_assay.rb +51 -0
  56. data/test/case_include_assay.rb +51 -0
  57. data/test/case_instance_assay.rb +51 -0
  58. data/test/case_kind_assay.rb +51 -0
  59. data/test/case_less_assay.rb +53 -0
  60. data/test/case_less_equal_assay.rb +53 -0
  61. data/test/case_like_assay.rb +57 -0
  62. data/test/case_match_assay.rb +45 -0
  63. data/test/case_more_assay.rb +53 -0
  64. data/test/case_more_equal_assay.rb +53 -0
  65. data/test/case_nil_assay.rb +48 -0
  66. data/test/case_nomatch_assay.rb +47 -0
  67. data/test/case_raise_assay.rb +51 -0
  68. data/test/case_respond_assay.rb +51 -0
  69. data/test/case_throw_assay.rb +51 -0
  70. data/test/case_true_assay.rb +48 -0
  71. data/test/case_unequal_assay.rb +55 -0
  72. data/test/case_within_assay.rb +61 -0
  73. data/test/helper.rb +36 -0
  74. metadata +135 -108
  75. data/APACHE2.txt +0 -205
  76. data/NOTICE.rdoc +0 -18
  77. data/lib/assay/assertions/compare_failure.rb +0 -61
  78. data/lib/assay/assertions/delta_failure.rb +0 -80
  79. data/lib/assay/assertions/empty_failure.rb +0 -76
  80. data/lib/assay/assertions/equality_failure.rb +0 -100
  81. data/lib/assay/assertions/execution_failure.rb +0 -90
  82. data/lib/assay/assertions/false_failure.rb +0 -72
  83. data/lib/assay/assertions/identity_failure.rb +0 -85
  84. data/lib/assay/assertions/instance_failure.rb +0 -76
  85. data/lib/assay/assertions/kind_failure.rb +0 -80
  86. data/lib/assay/assertions/match_failure.rb +0 -85
  87. data/lib/assay/assertions/nil_failure.rb +0 -75
  88. data/lib/assay/assertions/raise_failure.rb +0 -134
  89. data/lib/assay/assertions/response_failure.rb +0 -86
  90. data/lib/assay/assertions/same_failure.rb +0 -82
  91. data/lib/assay/assertions/throw_failure.rb +0 -122
  92. data/lib/assay/assertions/true_failure.rb +0 -79
  93. data/lib/assay/matcher.rb +0 -48
  94. data/qed/01_failure_classes.rdoc +0 -75
  95. data/qed/02_assertives.rdoc +0 -118
  96. data/qed/03_matchers.rdoc +0 -118
  97. data/qed/04_lookup.rdoc +0 -10
@@ -1,5 +1,11 @@
1
1
  = Assay
2
2
 
3
+ {Website}[http://rubyworks.github.com/assay] /
4
+ {Report Issue}[http://github.com/rubyworks/assay/issues] /
5
+ {Source Code}[http://github.com/rubyworks/assay] /
6
+ {Mailing List}[http://groups.google.com/group/rubyworks-mailinglist]
7
+
8
+
3
9
  == DESCRIPTION
4
10
 
5
11
  Assay defines assertions in the same way that Ruby defines
@@ -8,26 +14,21 @@ extended Exception class. Assay provides a complete set
8
14
  of these assertion classes for the most common assertion types.
9
15
  It also provides both TestUnit-style assertion methods and
10
16
  RSpec-compatiable matchers built from these assertion classes
11
- for use in your preferred test harness. Assay works with
17
+ for use in your preferred test harness. Assay is compatible with
12
18
  TestUnit, MiniTest, RSpec and other test frameworks.
13
19
 
14
20
 
15
21
  == FEATURES
16
22
 
17
- * Mirrors the Ruby Exception system.
18
- * Assertions get their own specialized error messages.
19
-
20
-
21
- == RESOURCES
23
+ * Patterned after the Ruby exception system.
24
+ * Allows assertions specialized error messages.
25
+ * Supports any variety of assertion "grammers".
26
+ * Can be used with almost any test framework.
22
27
 
23
- * home: http://rubyworks.github.com/assay
24
- * code: http://github.com/rubyworks/assay
25
- * mail: http://groups.google.com/group/rubyworks-mailinglist
26
28
 
29
+ == LIMITATIONS
27
30
 
28
- == SYNOPSIS
29
-
30
- See QED documentation.
31
+ * Assay is Ruby 1.9+ only!
31
32
 
32
33
 
33
34
  == INSTALLATION
@@ -40,11 +41,133 @@ Site installation with the tarball can be done with Ruby Setup
40
41
  (gem install setup). See http://rubyworks.github.com/setup.
41
42
 
42
43
 
43
- == COPYING
44
+ == UTILIZATION
45
+
46
+ === Assay Classes
47
+
48
+ Assay consists of a set of Assertion subclasses known as *assays*. They
49
+ are akin to Ruby's Exception subclasses, indeed the +Assertion+ base class
50
+ is a subclass of Exception. But assays have special class methods that are
51
+ used to make assertions.
52
+
53
+ Consider the +EqualityAssay+ class. It defines methods for asserting equality
54
+ via the `#==` method.
55
+
56
+ EqualityAssay.assert!(1,1)
57
+
58
+ Additionally, we can check the assertion's test without actually raising the
59
+ assertion if it fails using the query method.
60
+
61
+ EqualityAssay.pass?(1,1) #=> true
62
+
63
+ Assays also provide the opposite method `#refute!` along with `#fail?`.
64
+
65
+ EqualityAssay.refute!(1,2)
66
+
67
+ EqualityAssay.fail?(1,2) #=> true
68
+
69
+ Assay instances are test matchers, which can be conveniently defined with `#[]`.
70
+
71
+ EqualityAssay[1] =~ 1
72
+
73
+ Notice in the example we have used `#=~` to apply the matcher which makes
74
+ the `#assert!` call to the Assay object. Likewise `#!~` can be used to
75
+ call `#refute!` instead. And note that `#===` is also an alias for `#=~`.
76
+
77
+ EqualityAssay[1] === 1
78
+
79
+ Which means assay matchers can be used in case statments.
80
+
81
+ case 10
82
+ when InstanceAssay[Fixnum]
83
+ when EqualityAssay[10.0]
84
+ end
85
+
86
+ Pretty neat.
87
+
88
+ === Framework Adapters
89
+
90
+ Assay follows a standard practice of defining assertion error classes with
91
+ an `#assertion?` method that returns +true+. This can be used by any test
92
+ framework to easily detect when a raised error is an assertion rather than
93
+ an ordinary error. To add support for this to common test frameworks Assay
94
+ provides adapters.
95
+
96
+ For example, to use assay with MiniTest framework add to your test helper
97
+ script:
98
+
99
+ require 'assay/adapter/minitest'
100
+
101
+ Likewise for TestUnit.
102
+
103
+ require 'assay/adapter/testunit'
104
+
105
+ An RSpec adadpter is in the works, and should be out with the next release.
106
+
107
+ Note that even without the adapter, you can still use Assay with other test
108
+ frameworks. They will simply count Assay's assertions as regular errors.
109
+
110
+ === Customized Grammars
111
+
112
+ Of course the classes are interesting and clearly make for a sound foundation,
113
+ but in the end we want to write assertions more easily and concisely. For this
114
+ we turn to separate "grammar" projects that depend on Assay's classes. The
115
+ first of these, created as a spin-off project to demonstrate Assay's prowess,
116
+ is {Fluidity}[http://rubyworks.github.com/fluidity]. Here is a quick taste of
117
+ that gem's functionality.
118
+
119
+ require 'fluidity'
120
+
121
+ 10.should.be.kind_of(Integer)
122
+
123
+ But is you are acustom to MiniTest's spec methods, you might prefer `must`.
124
+
125
+ 10.must.be.kind_of(Integer)
126
+
127
+ And to satisfy all those technical aficionados (like yours truly) there is `assert`.
128
+
129
+ 10.assert.kind_of(Integer)
130
+
131
+ Thre are also compatibility grammar projects available, spun-off from Assay, that
132
+ provide compatability with legacy test frameworks which can serve as transition
133
+ to Assay from these other frameworks. Follow the links below for each:
134
+
135
+ * {Assay TestUnit}[http://github.com/rubyworks/assay-testunit]
136
+ * {Assay MiniTest}[http://github.com/rubyworks/assay-minitest]
137
+ * {Assay RSpec}[http://github.com/rubyworks/assay-rspec]
138
+
139
+ Usage is essentially the same for any one of them. For example,
140
+
141
+ require 'assay/rspec'
142
+
143
+ include Assay::Matchers
144
+
145
+ 10.should be_kind_of(Integer)
146
+
147
+ Note that the compatibility modules are not yet 100% compatable, lacking some
148
+ of the more esoteric and complex features. But they are very nearly so, and
149
+ will become more so in time.
150
+
151
+ These are just a few possible grammars. There is no reason not to build
152
+ your own grammar on top of Assay's classes if you have another approach in mind.
153
+ Indeed, please do! That, after all, is the main purpose of having such
154
+ a set of reusable assertion classes!
155
+
156
+ === Learning More
157
+
158
+ There's more learn about Assay, mainly the variety of assay classes available,
159
+ but also a few other bits of functionality not comvered here. To learn
160
+ about these check out the {QED documentation}[http://github.com/rubyworks/assay]
161
+ which provides an overiew of functionality with working examples, and the
162
+ the {API documentation}[http://rubydoc.info/gems/asasy] for a more in depth look
163
+ under the hood.
164
+
165
+
166
+ == COPYRIGHTS
44
167
 
45
- Copyright (c) 2009 Thomas Sawyer
168
+ Copyright (c) 2009 Rubyworks
46
169
 
47
- This program is ditributed under the terms of the Apache 2.0 license.
170
+ This program is ditributed under the terms of the *BSD-2-Cluase* license.
48
171
 
49
- See NOTICE.rdoc and APACHE2.txt file for details.
172
+ See COPYING.rdoc file for details.
50
173
 
@@ -1,44 +1,97 @@
1
- module Assay
2
- #VERSION="1.0.0"
3
-
4
- # Returns a Hash table of failure classes indexed by
5
- # asserton operator.
6
- def self.failure_classes_by_operator
7
- @_failure_classes_by_operator ||= (
8
- c = {}
9
- ObjectSpace.each_object(Class) do |fc|
10
- next unless fc < Assay::Assertion
11
- if fc.respond_to?(:assertion_operator)
12
- c[fc.assertion_operator.to_sym] = fc
13
- end
14
- end
15
- c
16
- )
17
- end
1
+ # Load Assay's assertion classes.
2
+ require_relative 'assay/assertion'
3
+ dir = File.dirname(__FILE__) + '/assay'
4
+ Dir.entries(dir).each do |file|
5
+ next if File.extname(file) != '.rb'
6
+ require_relative 'assay/' + file
7
+ end
18
8
 
19
- # Lookup failure class by operator.
20
- def self.lookup(operator)
21
- failure_classes_by_operator[operator.to_sym]
22
- end
9
+ module Assay
23
10
 
11
+ #
24
12
  # Returns Hash table of project metadata.
25
- def self.meta
13
+ #
14
+ def self.metadata
26
15
  @spec ||= (
27
16
  require 'yaml'
28
17
  YAML.load(File.new(File.dirname(__FILE__) + '/assay.yml'))
29
18
  )
30
19
  end
31
20
 
21
+ #
32
22
  # Check metadata for missing constants.
23
+ #
33
24
  def self.const_missing(name)
34
- meta[name.to_s.downcase] || super(name)
25
+ metadata[name.to_s.downcase] || super(name)
35
26
  end
36
- end
37
27
 
38
- # Load Assay's failure classes.
39
- dir = File.dirname(__FILE__)
40
- glob = File.join(dir, 'assay', 'assertions', '*.rb')
41
- Dir[glob].each do |rb|
42
- require 'assay/assertions/' + File.basename(rb)
28
+ #
29
+ # Returns a list of Assertion subclasses.
30
+ #
31
+ def self.assertions
32
+ Assertion.subclasses
33
+ end
34
+
35
+ #
36
+ # Set ANSI color mode. Default is false, so set to `true` to get ANSI color
37
+ # in some error messages.
38
+ #
39
+ # @example
40
+ # Assay.color = true
41
+ #
42
+ def self.color=(boolean)
43
+ if boolean
44
+ require 'ansi/diff'
45
+ $ansi = true
46
+ else
47
+ $ansi = false
48
+ end
49
+ end
50
+
51
+ #
52
+ # Lookup assay class by operator or name.
53
+ #
54
+ def self.lookup(symbol)
55
+ lookup_by_operator(symbol) || lookup_by_name(symbol)
56
+ end
57
+
58
+ #
59
+ # If operator is not given, returns a hash table of assertion classes
60
+ # indexed by operator.
61
+ #
62
+ def self.lookup_by_operator(operator=nil)
63
+ Assertion.by_operator(operator)
64
+ end
65
+
66
+ #
67
+ # If operator is not given, returns a hash table of assertion classes
68
+ # indexed by assertive name.
69
+ #
70
+ def self.lookup_by_name(name=nil)
71
+ Assertion.by_name(name)
72
+ end
73
+
74
+ # This module serves as the primary container for traditonal style assertion
75
+ # methods, which can be mixed in to one's testing scope (e.g. World).
76
+ #
77
+ module Assertions
78
+ end
79
+
80
+ # This module holds the subject matcher methods, which can be mixin
81
+ # to one's testing scope (e.g. World).
82
+ #
83
+ module Matchers
84
+ end
85
+
86
+ # This module holds the assertion extension mehods, which are mixed into
87
+ # the Object class.
88
+ #
89
+ module Extensions
90
+ end
91
+
92
+ #class ::Object
93
+ # include Assay::Extensions
94
+ #end
95
+
43
96
  end
44
97
 
@@ -1,44 +1,49 @@
1
- ---
2
- spec_version: 1.0.0
3
- replaces: []
4
-
5
- loadpath:
6
- - lib
7
- name: assay
8
- repositories: {}
9
-
10
- conflicts: []
11
-
12
- engine_check: []
13
-
14
- title: Assay
15
- resources:
16
- code: http://github.com/rubyworks/assay
17
- docs: http://rubydoc.info/gems/assay
18
- home: http://rubydoc.info/gems/assay
19
- maintainers: []
20
-
21
- requires:
22
- - group: []
23
-
24
- name: ansi
25
- version: ">=1.2.5"
26
- - group:
1
+ ---
2
+ source:
3
+ - meta
4
+ authors:
5
+ - name: Thomas Sawyer
6
+ email: transfire@gmail.com
7
+ copyrights:
8
+ - holder: Thomas Sawyer
9
+ year: '2009'
10
+ license: BSD-2-Clause
11
+ replacements: []
12
+ alternatives: []
13
+ requirements:
14
+ - name: ansi
15
+ - name: brass
16
+ - name: detroit
17
+ groups:
27
18
  - build
28
- name: redline
29
- version: 0+
30
- - group:
19
+ development: true
20
+ - name: qed
21
+ groups:
31
22
  - test
32
- name: qed
33
- version: 0+
34
- suite: rubyworks
35
- manifest: MANIFEST.txt
36
- version: 0.2.0
37
- licenses:
38
- - Apache 2.0
39
- copyright: Copyright (c) 2007 Thomas Sawyer
40
- authors:
41
- - Thomas Sawyer
42
- description: The Assay project defines Assertions in the same way that Ruby defines Exceptions. An asserition then simply becomes an extension to an Exception class.
23
+ development: true
24
+ dependencies: []
25
+ conflicts: []
26
+ repositories:
27
+ - uri: git@github.com:rubyworks/assay.git
28
+ scm: git
29
+ name: upstream
30
+ resources:
31
+ home: http://rubydoc.info/gems/assay
32
+ docs: http://rubydoc.info/gems/assay
33
+ code: http://github.com/rubyworks/assay
34
+ mail: http://groups.google.com/groups/rubyworks-mailinglist
35
+ extra: {}
36
+ load_path:
37
+ - lib
38
+ revision: 0
39
+ created: '2009-08-21'
43
40
  summary: Class-based Assertions Framework
44
- created: 2009-08-21
41
+ title: Assay
42
+ version: 0.4.0
43
+ name: assay
44
+ description: ! 'The Assay project defines Assertions in the same way that Ruby defines
45
+ Exceptions.
46
+
47
+ An asserition then simply becomes an extension to an Exception class.'
48
+ organization: Rubyworks
49
+ date: '2012-01-25'
@@ -0,0 +1,174 @@
1
+ require_relative 'assertor'
2
+
3
+ module Assay
4
+
5
+ module Assertable
6
+
7
+ $ASSERTION_COUNTS ||= Hash.new{ |h,k| h[k] = 0 } #{:total=>0,:pass=>0,:fail=>0}
8
+
9
+ #
10
+ # When displaying errors, use this as a rule of thumb
11
+ # for determining when the inspected object will be too
12
+ # big for a single line message.
13
+ #
14
+ SIZE_LIMIT = 13
15
+
16
+ # TODO: There's really no point to the defaults for #operator and
17
+ # assertive name b/c `register` is now reauired which set them.
18
+ # But that's in Assertion not Assertable, so something's not quite
19
+ # right in that regard.
20
+
21
+ #
22
+ # If the assertion coresponds to a regular method, particular a symbolic
23
+ # operator (hence the name of this method) then it should be specified via
24
+ # this interface. Otherwise, it should be given a fitting "make believe"
25
+ # method name and specified here. If not overridden it will be assumed
26
+ # to be the same as the `assertion_name` appended by `?`.
27
+ #
28
+ def operator
29
+ @operator ||= (name.split('::').last.chomp('Assay').downcase + '?').to_sym
30
+ end
31
+
32
+ #
33
+ # The assertive name is used for the construction of assertive nomenclatures
34
+ # such as `assert_equal`.
35
+ #
36
+ def assertive_name
37
+ @assertive_name ||= (
38
+ if operator.to_s.end_with?('?')
39
+ operator.to_s.chomp('?').to_sym
40
+ else
41
+ name.split('::').last.chomp('Assay').downcase.to_sym
42
+ end
43
+ )
44
+ end
45
+
46
+ #
47
+ # Create an assertor for the assay class, given +criteria+.
48
+ #
49
+ def assertor(*criteria, &block)
50
+ Assertor.new(self, *criteria, &block)
51
+ end
52
+
53
+ #
54
+ # Alias for `#assertor`.
55
+ #
56
+ def [](*criteria, &block)
57
+ assertor(*criteria, &block)
58
+ end
59
+
60
+ #
61
+ # Check the assertion, return `true` if passing, `false` otherwise.
62
+ #
63
+ def pass?(subject, *criteria, &block)
64
+ subject
65
+ end
66
+
67
+ #
68
+ # Check the assertion, return `true` if failing, `false` otherwise.
69
+ #
70
+ def fail?(subject, *criteria, &block)
71
+ ! pass?(subject, *criteria, &block)
72
+ end
73
+
74
+ #
75
+ # Test the assertion, raising the exception if failing.
76
+ #
77
+ def assert!(*arguments, &block)
78
+ options = (Hash === arguments.last ? arguments.pop : {})
79
+
80
+ backtrace = options[:backtrace] || caller
81
+ message = options[:message] || assert_message(*arguments, &block)
82
+
83
+ pass = pass?(*arguments, &block)
84
+
85
+ assert pass, self, message, backtrace
86
+
87
+ #if pass?(*arguments, &block)
88
+ # increment(:pass)
89
+ #else
90
+ # increment(:fail)
91
+ # fail self, message, backtrace
92
+ #end
93
+ end
94
+
95
+ #
96
+ # Test the refutation of the assertion.
97
+ #
98
+ # Test the inverse assertion, raising the exception if not failing.
99
+ #
100
+ def refute!(*arguments, &block)
101
+ options = (Hash === arguments.last ? arguments.pop : {})
102
+
103
+ backtrace = options[:backtrace] || caller
104
+ message = options[:message] || refute_message(*arguments, &block)
105
+
106
+ fail = fail?(*arguments, &block)
107
+
108
+ assert fail, self, message, backtrace
109
+
110
+ #if fail?(*arguments, &block)
111
+ # increment(:pass)
112
+ #else
113
+ # increment(:fail)
114
+ # fail self, message, backtrace
115
+ #end
116
+ end
117
+
118
+ ##
119
+ ##
120
+ ##
121
+ #def get_message(subject, fail=false)
122
+ # @not ^ fail ? refute_message(subject) : assert_message(subject)
123
+ #end
124
+
125
+ #
126
+ #
127
+ #
128
+ def assert_message(*arguments, &block)
129
+ standard_message(*arguments, &block)
130
+ end
131
+
132
+ #
133
+ #
134
+ #
135
+ def refute_message(*arguments, &block)
136
+ "! " + assert_message(*arguments, &block)
137
+ end
138
+
139
+ private
140
+
141
+ ##
142
+ ## Increment global `$ASSERTION_COUNTS` variable.
143
+ ##
144
+ #def increment(which)
145
+ # $ASSERTION_COUNTS[:total] += 1
146
+ # $ASSERTION_COUNTS[which.to_sym] += 1
147
+ #end
148
+
149
+ #
150
+ # Construct a standard error message.
151
+ #
152
+ def standard_message(*arguments, &block)
153
+ args_inspect = arguments.map{ |o| o.inspect }
154
+
155
+ op = self.operator.to_s
156
+ op = (/\w/ =~ op) ? ".#{op} " : " #{op} "
157
+
158
+ if args_inspect.any?{ |o| o.size > SIZE_LIMIT }
159
+ vars = ['b']
160
+ t = args_inspect.size - 2
161
+ t.times{ vars << vars.last.succ }
162
+
163
+ msg = ''
164
+ msg << "a#{op} " + vars.join(',') + "\n"
165
+ msg << args_inspect.join("\n")
166
+ msg
167
+ else
168
+ args_inspect.first + "#{op}" + args_inspect[1..-1].join(', ') + ""
169
+ end
170
+ end
171
+
172
+ end
173
+
174
+ end