It asks to implement the class Tester, which receives a class and and runs all its methods that start with the word test.
class AssertionFailed < Exception
end
class TestCase
def setUp
end
def tierDown
end
def assertTrue(expresion)
if not expresion then
raise AssertionFailed.new(expresion.to_s + " is not true")
end
end
def assertEquals(result, expected)
if result != expected
raise AssertionFailed.new(result.to_s + " is not equal to " + expected.to_s)
end
end
end
class IntegerTest < TestCase
def setUp
#number = 1
end
def testSum
assertTrue(1 + #number == 2)
#number += 1
end
def testSub
assertTrue(2 - #number == #number)
end
def testMulByZero
assertEquals(#number*0, 1)
end
def testAddByZero
assertEquals(#number + 0, #number + 1)
end
end
Tester.test(IntegerTest)
Example:
Tester.test(IntegerTest)
[*] testMulByZero failed: 0 is not equals to 1
[*] testAddByZero failed: 1 is not equals to 2
Help: The grep method of the Iterable module receives a regular expression, and returns all
The elements that match that expression. For the exercise, use grep (\ test * ) on
The collection of methods to obtain the methods sought.
I finally got an answer by this source and this one
What I have done is starting the test that is given, then i create an array by asking to de class testig his instace which start with test, finaly it's an iteration on the array asking to execute eachone of the methods and if they fail the assertion then show them
class Tester
def self.test(testing)
tested=testing.new
tested.setUp
method_arr=testing.instance_methods.grep(/test*/)
method_arr.each do |x|
begin
tested.send(:"#{x}")
rescue AssertionFailed =>assert_fail
puts "[*]" + "#{assert_fail}"
end
end
end
end
Related
hey I want that my method logify puts each method with its parameters and return value of my class A. I wrote for example a simple class A with two methods add and sub and the output should look like that:
Output:
Method add(1, 2) called
return value 3
Method sub(1, 2) called
return value -1
I know that I can get each method with self.instance_methods(false) but can someone please help me further?
require_relative "log"
class A
extend Log
def add(a, b)
a + b
end
def sub(a, b)
a - b
end
logify
end
a = A.new
a.add(2,1)
a.sub(2,1)
module Log
def logify
puts self.instance_methods(false)
end
end
You can use Module#prepend and Module#prepended to help with this like so:
module Log
def self.prepended(base)
base.instance_methods(false).each do |m|
define_method(m) do |*args, &block|
puts "Method #{m}(#{args.join(',')}) called"
val = super(*args, &block)
puts "return value #{val}"
val
end
end
end
end
class A
def add(a, b)
a + b
end
def sub(a, b)
a - b
end
end
A.prepend(Log)
What this does is it defines a method in the prepended module with the same name as the original then builds your output and delagets to the original method in the middle (super) to obtain the return value.
Examples
a = A.new
a.add(2,1)
# Method add(2,1) called
# return value 3
#=> 3
a.sub(2,1)
# Method sub(2,1) called
# return value 1
#=> 1
Caveat: this will only show the provided arguments and will not output default arguments in the method signature
The ruby core library includes the class TracePoint, which can be used to trace just about anything - from methods being defined, or invoked, or exceptions being raised, ...
Here is an example usage, which will perform the tracking you desired:
class A
def add(a, b)
a + b
end
def sub(a, b)
a - b
end
end
TracePoint.trace(:call, :return) do |tp|
next unless tp.defined_class == A
case tp.event
when :call
params = tp.parameters.map { |arg| eval(arg[1].to_s, tp.binding) }
puts "Method #{tp.method_id}(#{params.join(', ')}) called"
when :return
puts "return value #{tp.return_value}"
end
end
# The trace has been enabled! Any time one of those events occurs, the block is evaluated.
a = A.new
a.add(2,1)
a.sub(2,1)
Output:
Method add(2, 1) called
return value 3
Method sub(2, 1) called
return value 1
Fetching the params data is, as you can see, a little troublesome. TracePoint has access to the method signature, but you need to make use of the trace's binding to see what values it's actually been called with.
I have a class that does calculations. Most of the times it is used in the code to output a single value:
Use: value = Calculator.new(1234).output
This is an example of the class definition:
class Calculator
def initialize(parameter_1)
#parameter_1 = parameter_1
end
def output
op_1_result = operation_1(#parameter_1)
op_2_result = operation_2(op_1_result)
operation_3(op_2_result)
end
def operation_1(param)
...
end
But sometimes the user has to print a report of the calculation, showing many of the variables from inside the calculations.
The first solution I implemented was to pass a parameter at initialization telling the class that it should save some internal variables for the report, like this:
class Calculator
attr_reader :report
def initialize(parameter_1, reporting=false)
#parameter_1 = parameter_1
#reporting = reporting
#report = {}
end
def output
op_1_result = operation_1(#parameter_1)
#report[:op_1_result] = op_1_result if #reporting
op_2_result = operation_2(op_1_result)
#report[:op_2_result] = op_2_result if #reporting
operation_3(op_2_result)
end
def operation_1(param)
...
end
Then, when I want to get those intermediate variables, I would:
calculator = Calculator.new(1234, true) # reporting activated
report = calculator.report
report[:op_1_result] # one of the intermediate variables of the calculation
Does this break the single responsibility principle, as the class is now calculating the value and reporting at the same time?
Is there a better way to do this, a design pattern where I could have a fast calculation of the output result where it is needed and show the report where needed without all those ifs?
Any light on this and comments will be really appreciated!
Obs (another discussion): I've read that a more functional approach to just outputting a value would be a great thing. But that kept me wondering about how to show those internal intermediate values when needed. How do more functional programmers would do it...?
I guess "builder pattern" is suitable and "report pad" should be injected from outside.
class Calculator
def initialize(*parameters)
#parameters = parameters
end
def report_to(report_pad)
#report_pad = report_pad
self
end
def output()
ret = #parameters[0].to_i + #parameters[1].to_i
report('Did p0 + p1')
ret
end
private
def report(message)
#report_pad << "\n".prepend(message) if #report_pad.respond_to? '<<'
end
end
####
reports = ""
result = Calculator
.new(1, 2)
.report_to(reports)
.output()
puts result, reports
Why don't you just make all intermediate results public methods and chain the results in the final output?
Perhaps something like this:
class Calculator
def initialize(parameter)
#parameter = parameter
end
def output
op_3_result
end
def op_1_result
#op_1_result ||= operation_1(parameter)
end
def op_2_result
#op_2_result ||= operation2(op_1_result)
end
def op_3_result
#op_3_result ||= operation3(op_2_result)
end
private
def operation1(arg)
# ...
end
def operation2(arg)
# ...
end
def operation3(arg)
# ...
end
attr_reader :parameter
end
That would allow you to call whatever you need on the same instance:
calculator = Calculator.new(1234)
calculator.output #=> the final result
calculator.op_2_result #=> the intermediate result of step 2
You could use a different pattern with Report being its own class and allow it to just pass through when reporting is turned off. Here is a simple example:
class Calculator
attr_reader :report
def initialize(parameter_1, reporting=false)
#parameter_1 = parameter_1
#report = Report.new(reporting)
end
def output
op1 = operation_1(report.capture(:param1,#parameter_1))
report.capture(:op1,op1)
op2 = report.capture(:op2) { operation_2(op1) }
operation_3(op2)
end
def operation_1(param);
param + 7
end
def operation_2(param);
param - 3
end
def operation_3(param);
param * 2
end
end
class Report
attr_reader :reporting, :reportables
def initialize(reporting)
#reporting = reporting
#reportables = {}
end
def capture(key, val=nil,&block)
warn "Block supercedes value" if val && block_given?
result = block_given? ? block.call : val
#reportables[key] = result if reporting
result
end
def [](key)
return 'No Reporting' unless reporting
#reportables[key]
end
end
Then you can use like so
c = Calculator.new(12)
c.output
#=> 32
c.report[:op1]
#=> "No Reporting"
c = Calculator.new(12, true)
c.output
#=> 32
c.report[:op1]
#=> 19
c.report[:param1]
#=> 12
This way each step can use a block for more complicated items where the result should be captured or just pass a value if you choose and intermediate steps like operation_3 (in this case) that do not need to be "captured" can just flow through.
If reporting is off then everything just flows through and the captures are ignored.
Your #output method could also look like this (no intermediate locals at all although it does hurt the readability a bit)
def output
operation_3 (
report.capture(:op2,
operation_2(
report.capture(:op1) do
operation_1(report.capture(:param1,#parameter_1))
end
)
)
)
end
You can use dependency injection like this:
class Calculator
def initialize(parameter_1, reporter = nil)
#parameter_1 = parameter_1
#reporter = reporter
end
def output
op_1_result = call_with_reporting :operation_1, #parameter_1
op_2_result = call_with_reporting :operation_2, op_1_result
operation_3(op_2_result)
end
def operation_1(param)
...
end
def call_with_reporting(operation, *args)
result = self.send(operation, *args)
#reporter.report(operation, result) if #reporter
result
end
end
class ConsoleReporter
def initialize
#results = {}
end
def report(operation, result)
#results[operation] = result
end
def run_report
puts #operations
end
end
Now you can use Calculator like this:
reporter = ConsoleReporter.new
Calculator.new(12, reporter).output
reporter.run_report
Later you can use Calculator with other format reporter (like ToFileReporter)
I am having problems refactoring out some duplicated code from two methods sharing a for loop. The two methods with the duplicated code are gcdOfFiveUpToFive and remainderStepsUpToFive. The two loops share in common setting instance variable #m to 5 and the both use a for x in 1..5 loop and then set #n to x as well as both of them need to call euclidGCD although one calls euclidGCD for its return value and the other to add +=1 to the #count variable. I do want want to return 2 values from one method. I guess I could make a 4th instance variable called #countArray and get an array of the remainder step count.
require 'minitest/autorun'
class GCDTest < Minitest::Test
def test_euclid_gcd
gcdTestObject=GCD.new(20,5)
assert gcdTestObject.euclidGcd==5
assert gcdTestObject.gcdRemainderSteps==1
end
def test_euclid_two
gcdTestObject=GCD.new(13,8)
assert gcdTestObject.euclidGcd==1
assert gcdTestObject.gcdRemainderSteps==5
end
def test_euclid_loop
gcdTestObject=GCD.new(0,0)
assert gcdTestObject.gcdOfFiveUpToFive==[1,1,1,1,5]
end
def test_count_of_loop
gcdTestObject=GCD.new(0,0)
assert gcdTestObject.remainderStepsUpToFive==[1,2,3,2,1]
end
end
class GCD
attr_accessor :m,:n
attr_reader :count
def initialize(m,n)
#m=m
#n=n
#count=0
end
def euclidGcd
#count=1
m=#m
n=#n
r= m % n
until r==0
m=n
n=r
r= m % n
#count+=1
end
return n
end
def gcdRemainderSteps
return #count
end
def gcdOfFiveUpToFive
#m=5
gcdArrayUpToFive=[]
for x in 1..5
#n=x
gcdArrayUpToFive << euclidGcd
end
return gcdArrayUpToFive
end
def remainderStepsUpToFive
#m=5
gcdStepArrayUpToFive=[]
for x in 1..5
#n=x
euclidGcd
gcdStepArrayUpToFive << gcdRemainderSteps
end
return gcdStepArrayUpToFive
end
def fiveLoopExtraction
end
Code that repeats itself is this:
array=[]
for x in 1..5
# result = do something with x
array << result
end
return array
That is exactly what map function does.
What does the "map" method do in Ruby?
Ruby methods names should be snake_case. Lets refactor this to use proper naming convention and map function.
def gcd_of_five_up_to_five
#m=5
(1..5).map do |x|
#n = x
# in ruby you don't have to write return
# value of last expression is returned automatically
euclid_gcd
end
end
def remainder_steps_up_to_five
#m=5
(1..5).map do |x|
#n = x
euclid_gcd
gcd_remainder_steps
end
end
I'd call it with params instead of using #m and #n. That would simplify the code. If you change euclid_gcd to this: def euclid_gcd(m:, n:) you'd get this:
def gcd_of_5_up_to_5
(1..5).map { |x| euclid_gcd(m: 5, n: x) }
end
def remainder_steps_up_to_5
(1..5).map do |x|
euclid_gcd(m: 5, n: x)
gcd_remainder_steps
end
end
Seems like this needs little or no further refactoring.
I try to define operational semantics in Ruby, just for learning purposes. And I'd like to define operations like: add, multiply, subtraction, division.
Here is code:
class Operation < Struct.new(:left, :right)
def inspect
"#{self}"
end
def reducible?
true
end
end
class Add < Operation
def to_s
"#{left} + #{right}"
end
def reduce
if left.reducible?
Add.new(left.reduce, right)
elsif right.reducible?
Add.new(left, right.reduce)
else
Number.new(left.value + right.value)
end
end
end
class Multiply < Operation
def to_s
"#{left} * #{right}"
end
def reduce
if left.reducible?
Multiply.new(left.reduce, right)
elsif right.reducible?
Multiply.new(left, right.reduce)
else
Number.new(left.value + right.value)
end
end
end
Is it possible to have the same thing, but define reduce in Operation class, but create instance of some particular child class in Operation class?
Thanks in advance.
Yes.
class Operation
def reduce
if left.reducible?
self.class.new(left.reduce, right)
elsif right.reducible?
self.class.new(left, right.reduce)
else
Number.new(left.value + right.value)
end
end
end
I am trying to write a simple DSL (against Redis) and I would like to define []+= myself
I have
def []=(key,val)
#redis.zadd(#name,val,key)
end
and I would like to define
def []+=(key,val)
#redis.zincrby(#name,val,key)
end
But my understanding is that Ruby provides the "[]+=" operator automaticallygiven []=
Is there a way to over-ride this behavior
Obviously I don't want this because I would not be able to, say, run this in pipeline mode
No, <operator>= can not be redefined in Ruby.
You can try to get really fancy and wrap your return values in classes that delegate to the actual value. This way, they behave like the actual value, but you can play tricks, for instance with +.
Here's a simple example:
require 'delegate'
module Redis
class Set
class Value < SimpleDelegator
def +(val)
Increment.new(self, val)
end
end
class Increment < SimpleDelegator
attr_reader :increment
def initialize(source, increment)
super(source.__getobj__ + increment)
#increment = increment
end
end
def [](key)
Value.new(#redis.not_sure_what(#name, key))
end
def []=(key,val)
if val.is_a?(Increment)
#redis.zincrby(#name,val.increment,key)
else
#redis.zadd(#name,val,key)
end
end
end
end
This is just a starting point. You'll have to be more careful than this, for example by checking the key is the same. In my simplistic example, redis[:foo] = redis[:bar] + 1 would actually be equivalent to redis[:foo] += 1...
Nope. x[y] += z expands to exactly x[y] = x[y] + z:
class << (object = Object.new)
def [](key)
puts "[#{key.inspect}]"
key
end
def []=(key, value)
puts "[#{key.inspect}] = #{value.inspect}"
value
end
end
# These are all equivalent
object['See?'] += " It's impossible."
object['See?'] = object['See?'] + " It's impossible."
object.[]=('See?', object.[]('See?').+(" It's impossible."))
# They all produce the same output:
# ["See?"]
# ["See?"] = "See? It's impossible."
# => "See? It's impossible."
You will have to create a separate method.