How to test a loop with shuffle in Ruby? - ruby

How to test in Ruby
if shuffle
some_array.shuffle.each { |val| puts "#{val}" }
end
Do I need to test shuffle or no since it is a Ruby method? Thanks.

Short answer: No.
You can trust that Ruby will do things correctly. It has a huge number of tests already.
Long answer: Yes.
You shouldn't be testing the shuffle method directly, but testing that your code produces the correct results.
Since your code uses puts this makes it very annoying to test. If you can write a method that returns values that can be printed, that's usually a lot better. When writing code always think about how you can test it.
If you're struggling with that, where the way to test something isn't clear, write the tests first and then write code to make them pass.
If it's imperative that your values be shuffled then you'll need to come up with a way of determining if they're sufficiently shuffled. This can be difficult since randomness is a fickle thing. There's a small but non-zero chance that shuffle does nothing to your data, that's how randomness works. This probability grows considerably the smaller your list is to the point where it's guaranteed to do nothing with just one element.
So if you can describe why the data should be shuffled, and what constitutes a good shuffling, then you can write a test for this.
Here's an example of how to do that:
gem 'test-unit'
require 'test/unit'
class MyShuffler
def initialize(data)
#data = data
end
def processed
#data.map do |e|
e.downcase
end.shuffle
end
end
Now you can use this like this:
shuffler = MyShuffler.new(%w[ a b c d e f ])
# Thin presentation layer here where we're just displaying each
# element. Test code for this is not strictly necessary.
shuffler.processed.each do |e|
puts e
end
Now you write test code for the data manipulation in isolation, not the presentation part:
gem 'test-unit'
require 'test/unit'
class MyShufflerTest < Test::Unit::TestCase
def test_processed
shuffler = MyShuffler.new(%w[ A B c Dee e f Gee ])
results = shuffler.processed
expected = %w[ a b c dee e f gee ]
assert_equal expected, results.sort
assert_not_equal expected, results
counts = Hash.new(0)
iterations = 100000
# Keep track of the number of times a particular element appears in
# the first entry of the array.
iterations.times do
counts[shuffler.processed[0]] += 1
end
expected_count = iterations / expected.length
# The count for any given element should be +/- 5% versus the expected
# count. The variance generally decreases with a larger number of
# iterations.
expected.each do |e|
assert (counts[e] - expected_count).abs < iterations * 0.05
end
end
end

You should not test randomness using unit test. A unit test should call a method and test the returned value (or object state) against an expected value. The problem with testing randomness is that there isn't an expected value for most of the things you'd like to test.

Related

What is prefered way to loop in Ruby?

Why is each loop preferred over for loop in Ruby? Is there a difference in time complexity or are they just syntactically different?
Yes, these are two different ways of iterating over, But hope this calculation helps.
require 'benchmark'
a = Array( 1..100000000 )
sum = 0
Benchmark.realtime {
a.each { |x| sum += x }
}
This takes 5.866932 sec
a = Array( 1..100000000 )
sum = 0
Benchmark.realtime {
for x in a
sum += x
end
}
This takes 6.146521 sec.
Though its not a right way to do the benchmarking, there are some other constraints too. But on a single machine, each seems to be a bit faster than for.
The variable referencing an item in iteration is temporary and does not have significance outside of the iteration. It is better if it is hidden from outside of the iteration. With external iterators, such variable is located outside of the iteration block. In the following, e is useful only within do ... end, but is separated from the block, and written outside of it; it does not look easy to a programmer:
for e in [:foo, :bar] do
...
end
With internal iterators, the block variable is defined right inside the block, where it is used. It is easier to read:
[:foo, :bar].each do |e|
...
end
This visibility issue is not just for a programmer. With respect to visibility in the sense of scope, the variable for an external iterator is accessible outside of the iteration:
for e in [:foo] do; end
e # => :foo
whereas in internal iterator, a block variable is invisible from outside:
[:foo].each do |e|; end
e # => undefined local variable or method `e'
The latter is better from the point of view of encapsulation.
When you want to nest the loops, the order of variables would be somewhat backwards with external iterators:
for a in [[:foo, :bar]] do
for e in a do
...
end
end
but with internal iterators, the order is more straightforward:
[[:foo, :bar]].each do |a|
a.each do |e|
...
end
end
With external iterators, you can only use hard-coded Ruby syntax, and you also have to remember the matching between the keyword and the method that is internally called (for calls each), but for internal iterators, you can define your own, which gives flexibility.
each is the Ruby Way. Implements the Iterator Pattern that has decoupling benefits.
Check also this: "for" vs "each" in Ruby
An interesting question. There are several ways of looping in Ruby. I have noted that there is a design principle in Ruby, that when there are multiple ways of doing the same, there are usually subtle differences between them, and each case has its own unique use, its own problem that it solves. So in the end you end up needing to be able to write (and not just to read) all of them.
As for the question about for loop, this is similar to my earlier question whethe for loop is a trap.
Basically there are 2 main explicit ways of looping, one is by iterators (or, more generally, blocks), such as
[1, 2, 3].each { |e| puts e * 10 }
[1, 2, 3].map { |e| e * 10 )
# etc., see Array and Enumerable documentation for more iterator methods.
Connected to this way of iterating is the class Enumerator, which you should strive to understand.
The other way is Pascal-ish looping by while, until and for loops.
for y in [1, 2, 3]
puts y
end
x = 0
while x < 3
puts x; x += 1
end
# same for until loop
Like if and unless, while and until have their tail form, such as
a = 'alligator'
a.chop! until a.chars.last == 'g'
#=> 'allig'
The third very important way of looping is implicit looping, or looping by recursion. Ruby is extremely malleable, all classes are modifiable, hooks can be set up for various events, and this can be exploited to produce most unusual ways of looping. The possibilities are so endless that I don't even know where to start talking about them. Perhaps a good place is the blog by Yusuke Endoh, a well known artist working with Ruby code as his artistic material of choice.
To demonstrate what I mean, consider this loop
class Object
def method_missing sym
s = sym.to_s
if s.chars.last == 'g' then s else eval s.chop end
end
end
alligator
#=> "allig"
Aside of readability issues, the for loop iterates in the Ruby land whereas each does it from native code, so in principle each should be more efficient when iterating all elements in an array.
Loop with each:
arr.each {|x| puts x}
Loop with for:
for i in 0..arr.length
puts arr[i]
end
In the each case we are just passing a code block to a method implemented in the machine's native code (fast code), whereas in the for case, all code must be interpreted and run taking into account all the complexity of the Ruby language.
However for is more flexible and lets you iterate in more complex ways than each does, for example, iterating with a given step.
EDIT
I didn't come across that you can step over a range by using the step() method before calling each(), so the flexibility I claimed for the for loop is actually unjustified.

Is it possible to use methods from Ruby library in my own class?

I am trying to define Ruby classes for vectors and matrices. I intend to define two classes, MyVector and MyMatrix, with methods as hinted below. MyVector should represent a row vector, MyMatrix should represent a matrix, internally organized as an array of MyVector objects. Intended methods for MyVector:
#initialize method, that takes an array of integers as argument.
#length method, that returns the size of the vector.
#* method, taking argument a, that:
if a is a vector, returns the inner product, validating that the size of a matches the receiver.
if a is a matrix, then it returns the product of the receiver and the matrix, validating the size compatibility.
#to_s method, that returns a string representation of the receiver.
Methods for MyMatrix:
#initialize method, that takes an array of arrays as argument, converts the inner arrays into row vecotrs (MyVector class), and arranges them into a matrix.
#transpose method, that returns the receiver transposed.
#* method, that takes MyMatrix object argument and returns the matrix product, validating size compatibility of the argument.
#to_s method, that returns a string representation of the receiver.
This code I have written so far is below, but it doesn't work at all. I tried to define some method followed by the library class method (in matrix and vector class, they already define those method), but seem this way doesn't work because it always asks you to define something new. Could you please help me? Thanks!
class MyVector
def initialize (a)
if !(a.instance_of? Array)
raise "must be an array"
else
#array = a
end
end
def array
#array
end
def to_s
#array.to_s
end
def length
#array.length
end
def each2(a) #
raise Error, "Integer is not like Vector" if a.kind_of?(Integer)
Vector.Raise Error if length != a.length
return to_enum(:each2, a) unless block_given?
length.times do |i|
yield #array[i], a[i]
end
self
end
def * (a)
Vector.Raise Error if length != a.length
p = 0
each2(a) {|a1, a2|p += a1 * a2}
p
end
end
class MyMatrix
def initialize a
#array=Array.new(a.length)
i=0
while(i<a.length)
#array[i]=MyVector.new(a[i])
end
end
def to_s
#array.to_s
end
def transpose
size=vectors[0].length
arr= Array.new(size)
i=0
while i<size
a=Array.new(vector.length)
j=0
while j<a.length
a[j]=vectors[j].arr[i]
j+=1
end
arr[i]=a
i+=1
end
arr[i]=a
i+=1
end
def *m
if !(m instance_of? MyMatrix)
raise Error
a=Array.new(#array.length)
i=0
while (i<#array.length)
a[i]=#array[i]*m
i=i+1
end
end
end
end
A great question, and a great exercise for a newbie. As you might already know, Marc-André Lafortune has written the basic Matrix / Vector library, that is a part of Ruby standard library. While after the amount of effort that a programmer and mathematician, that Marc-André is, has put in the project, it is no longer possible to say that it sucks, it is also fair to say that stdlib matrix nowadays does not yet conform to that heavenly, dream-like quality that we expect of Ruby libraries.
My major criticism is that, just like you, Marc-André also makes a distinction between Vector and Matrix classes. This distinction shouldn't be: Vectors are simly matrices, whose second dimension is equal to 1. Separating Matrix and Vector leaves the user at loss as to which one to use, and that led me to banning Vector completely in the code that I write.
Neveretheless, it will be stdlib's matrix, that is going to be the answer to your post. If I understood it well, the question mark statement in your post seems to be:
"I tried to define some method ... but seem this way doesn't work because it always asks you to define something new. Could you please help me?"
In order to help you, I would answer: Start by using the matrix standard library. Simply type
require 'matrix'
In the next step, you will make a private copy of matrix library, that came with your Ruby installation, you will rename it to my_matrix, and require it no longer by require 'matrix', but by:
require './path/to/my/project/directory/my_matrix'
In the third step, you will start changing the behavior of the library that you just copied, and see when it breaks. Next, you will learn about unit testing, and learn to use stdlib's minitest. With that, you can define the desired behavior, and change the code until it meets the requirement.
In the 4th, 5th, ... nth step, you will be making a lot of big and small mistakes. And should your dedication to matrices and vectors in Ruby survive, you will be warmly welcome as a member of NMatrix team, the future grand version of representing matrices in Ruby.

Ruby yield example explanation?

I'm doing a SaaS course with Ruby. On an exercise, I'm asked to calculate the cartesian product of two sequences by using iterators, blocks and yield.
I ended up with this, by pure guess-and-error, and it seems to work. But I'm not sure about how. I seem to understand the basic blocks and yield usage, but this? Not at all.
class CartProd
include Enumerable
def initialize(a,b)
#a = a
#b = b
end
def each
#a.each{|ae|
#b.each{|be|
yield [ae,be]
}
}
end
end
Some explanation for a noob like me, please?
(PS: I changed the required class name to CartProd so people doing the course can't find the response by googling it so easily)
Let's build this up step-by-step. We will simplify things a bit by taking it out of the class context.
For this example it is intuitive to think of an iterator as being a more-powerful replacement for a traditional for-loop.
So first here's a for-loop version:
seq1 = (0..2)
seq2 = (0..2)
for x in seq1
for y in seq2
p [x,y] # shorthand for puts [x, y].inspect
end
end
Now let's replace that with more Ruby-idiomatic iterator style, explicitly supplying blocks to be executed (i.e., the do...end blocks):
seq1.each do |x|
seq2.each do |y|
p [x,y]
end
end
So far, so good, you've printed out your cartesian product. Now your assignment asks you to use yield as well. The point of yield is to "yield execution", i.e., pass control to another block of code temporarily (optionally passing one or more arguments).
So, although it's not really necessary for this toy example, instead of directly printing the value like above, you can yield the value, and let the caller supply a block that accepts that value and prints it instead.
That could look like this:
def prod(seq1, seq2)
seq1.each do |x|
seq2.each do |y|
yield [x,y]
end
end
end
Callable like this:
prod (1..2), (1..2) do |prod| p prod end
The yield supplies the product for each run of the inner loop, and the yielded value is printed by the block supplied by the caller.
What exactly do you not understand here? You've made an iterator that yields all possible pairs of elements. If you pass CartProd#each a block, it will be executed a.length*b.length times. It's like having two different for cycles folded one into another in any other programming language.
yield simply passes (yields) control to a block of code that has been passed in as part of the method call. The values after the yield keyword are passed into the block as arguments. Once the block has finished execution it passes back control.
So, in your example you could call #each like this:
CartProd.new([1, 2], [3, 4]).each do |pair|
# control is yielded to this block
p pair
# control is returned at end of block
end
This would output each pair of values.

Guidance with benchmarking some string splitting etc

I want to load an array with 1million guids, then loop through them and perform some string operations on each element of the array.
I only want to benchmark the time for the operations I perform on each element of the array, not the time it takes to initialize the array with 1 million rows.
I tried doing a benchmark before, but I didn't understand the output.
How would you do this, I have:
rows = []
(1..1000000).each do |x|
rows[x] = // some string data
end
n = 50000
Benchmark.bm do |x|
rows.each do |r|
# perform string logic here
end
end
Will this return consistent results?
Any guidance/gotcha's I should know about?
Yes, this will return consistent results. You need to report the benchmark, however and (if processing a million rows is too fast) you will need to use your n variable to iterate a few times. (Start with a low n and increase it if your times are in the tenth or hundredths of a second).
require 'benchmark'
# Prepare your test data here
n = 1
Benchmark.bm do |x|
x.report('technique 1') do
n.times do
# perform your string logic here
end
end
x.report('technique 2') do
n.times do
# perform your alternative logic here
end
end
end
Make sure you run your multiple comparisons in the same Benchmark block; don't write one attempt, write down the numbers, and then change the code to run it again. Not only is that more work for you, but it also may produce incorrect comparisons if your machine is in a different state (or if, heaven forfend, you run one test on one machine and another test on another machine).

What's the best way to test this?

I'm going through the EdgeCase Ruby Koans. In about_dice_project.rb, there's a test called "test_dice_values_should_change_between_rolls", which is straightforward:
def test_dice_values_should_change_between_rolls
dice = DiceSet.new
dice.roll(5)
first_time = dice.values
dice.roll(5)
second_time = dice.values
assert_not_equal first_time, second_time,
"Two rolls should not be equal"
end
Except for this comment that appears there:
# THINK ABOUT IT:
#
# If the rolls are random, then it is possible (although not
# likely) that two consecutive rolls are equal. What would be a
# better way to test this.
Which (obviously) got me thinking: what is the best way to reliably test something random like that (specifically, and generally)?
IMHO most answers so far have missed the point of the Koan question, with the exception of #Super_Dummy. Let me elaborate on my thinking...
Say that instead of dice, we were flipping coins. Add on another constraint of only using one coin in our set, and we have a minimum non-trivial set that can generate "random" results.
If we wanted to check that flipping the "coin set" [in this case a single coin] generated a different result each time, we would expect the values of each separate result to be the same 50% of the time, on a statistical basis. Running that unit test through n iterations for some large n will simply exercise the PRNG. It tells you nothing of substance about the actual equality or difference between the two results.
To put it another way, in this Koan we're not actually concerned with the values of each roll of the dice. We're really more concerned that the returned rolls are actually representations of different rolls. Checking that the returned values are different is only a first-order check.
Most of the time that will be sufficient - but very occasionally, randomness could cause your unit test to fail. That's not a Good Thing™.
If, in the case that two consecutive rolls return identical results, we should then check that the two results are actually represented by different objects. This would allow us to refactor the code in future [if that was needed], while being confident that the tests would still always catch any code that didn't behave correctly.
TL;DR?
def test_dice_values_should_change_between_rolls
dice = DiceSet.new
dice.roll(5)
first_time = dice.values
dice.roll(5)
second_time = dice.values
assert_not_equal [first_time, first_time.object_id],
[second_time, second_time.object_id], "Two rolls should not be equal"
# THINK ABOUT IT:
#
# If the rolls are random, then it is possible (although not
# likely) that two consecutive rolls are equal. What would be a
# better way to test this.
end
I'd say the best way to test anything that involves randomness is statistically. Run your dice function in a loop a million times, tabulate the results, and then run some hypothesis tests on the results. A million samples should give you enough statistical power that almost any deviations from correct code will be noticed. You are looking to demonstrate two statistical properties:
The probability of each value is what you intended it to be.
All rolls are mutually independent events.
You can test whether the frequencies of the dice rolls are approximately correct using Pearson's Chi-square test. If you're using a good random nunber generator, such as the Mersenne Twister (which is the default in the standard lib for most modern languages, though not for C and C++), and you're not using any saved state from previous rolls other than the Mersenne Twister generator itself, then your rolls are for all practical purposes independent of one another.
As another example of statistical testing of random functions, when I ported the NumPy random number generators to the D programming language, my test for whether the port was correct was to use the Kolmogorov-Smirnov test to see whether the numbers generated matched the probability distributions they were supposed to match.
There is no way to write a state-based test for randomness. They are contradictory, since state-based tests proceed by giving known inputs and checking output. If your input (random seed) is unknown, there is no way to test.
Luckily, you don't really want to test the implementation of rand for Ruby, so you can just stub it out with an expectation using mocha.
def test_roll
Kernel.expects(:rand).with(5).returns(1)
Diceset.new.roll(5)
end
It seems like there are 2 separate units here. First, a random number generator. Second, a "dice" abstraction that uses the (P)RNG.
If you want to unit test the dice abstraction, then mock out the PRNG calls, and make sure it calls them, and returns an appropriate value for the input you give, etc.
The PRNG is probably part of your library/framework/OS and so I wouldn't bother testing it. Maybe you'll want an integration test to see if it returns reasonable values, but that's a whole 'nother problem.
Instead of comparing values, compare object_id:
assert_not_equal first_time.object_id, second_time.object_id
This assumes that other tests will check for array of integers.
My solution was to allow a block to be passed to the roll function.
class DiceSet
def roll(n)
#values = (1..n).map { block_given? ? yield : rand(6) + 1 }
end
end
I can then pass my own RNG into the tests like this.
dice = DiceSet.net
dice.roll(5) { 1 }
first_result = dice.values
dice.roll(5) { 2 }
second_result = dice.values
assert_not_equal first_result, second_result
I don't know if that's really better, but it does abstract out the calls to the RNG. And it doesn't change the standard functionality.
Just create new array each time roll method called. This way you can use
assert_not_same first_time, second_time,
"Two rolls should not be equal"
to test object_id equality.
Yes, this test depends on implementation, but there is no way to test randomness.
Other approach is to use mocks as floyd suggested.
IMHO, randomness should be tested with dependency injection.
Jon Skeet answered to the general answer of how to test randomness here
I suggest you treat your source of randomness (a random number generator or whatever) as a dependency. Then you can test it with known inputs by providing either a fake RNG or one with a known seed. That removes the randomness from the test, while keeping it in the real code.
Example code of in our case may look something like this:
class DependentDiceSet
attr_accessor :values, :randomObject
def initialize(randomObject)
#randomObject = randomObject
end
def roll(count)
#values = Array.new(count) { #randomObject.userRand(1...6) }
end
end
class MyRandom
def userRand(values)
return 6
end
end
class RubyRandom
def userRand(values)
rand(values)
end
end
A user can inject any random behavior and test that the dice are rolled by that behavior. I implement ruby random behavior and another one that return always 6.
Usage:
randomDice = DependentDiceSet.new(RubyRandom.new)
sixDice = DependentDiceSet.new(MyRandom.new)
It seems a bit silly, to me. Are you supposed to be testing that the (psuedo) random number generator is generating random numbers? That's futile and pointless. If anything, you could test that dice.roll calls to your PRNG.
I solved the problem using recursion:
def roll times, prev_roll=[]
#values.clear
1.upto times do |n|
#values << rand(6) + 1
end
roll(times, prev_roll) if #values == prev_roll
end
And had to add a dup method to the test variable, so it doesn't pass the reference to my instance variable #values.
def test_dice_values_should_change_between_rolls
dice = DiceSet.new
dice.roll(5)
first_time = dice.values.dup
dice.roll(5, first_time)
second_time = dice.values
assert_not_equal first_time, second_time,
"Two rolls should not be equal"
end
rand is deterministic and depends on its seed. Use srand with a given number before the first roll and srand with a different number before the second roll. That would prevent repeating the series.
srand(1)
dice.roll(5)
first_time = dice.values
srand(2)
dice.roll(5)
second_time = dice.values
assert_not_equal first_time, second_time,
"Two rolls should not be equal"
i just created a new instance
def test_dice_values_should_change_between_rolls
dice1 = DiceSet.new
dice2 = DiceSet.new
dice1.roll(5)
first_time = dice1.values.dup
dice2.roll(5, first_time)
second_time = dice2.values
assert_not_equal first_time, second_time,
"Two rolls should not be equal"
end
The pragmatic approach is simply to test with a higher number of rolls. (The assumption being that this test is for two consecutive rolls of the same number).
likelihood of two 5 roll sets being the same => 6**5 => 1 in 7776
likelihood of two 30 roll sets being the same => 6**30 => 1 in 221073919720733357899776 (likelihood of hell freezing over)
This would be simple, performant and accurate [enough].
(We can't use object_id comparison since tests should be implementation agnostic and the implementation could be using the same array object by using Array#clear, or the object_id may have been reused, however unlikely)
I solved it by simply creating a new set of values for each dice anytime the 'roll' method is called:
def roll(n)
#numbers = []
n.times do
#numbers << rand(6)+1
end
end

Resources