Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I test `rand()` with RSpec?

Tags:

I have a method that does something like this:

def some_method   chance = rand(4)   if chance == 1 do     # logic here   else     # another logic here   end end 

When I use RSpec to test this method, rand(4) inside it always generates 0. I am not testing rand method of Rails, I am testing my method. What is a common practice to test my method?

like image 951
konnigun Avatar asked Jun 19 '13 15:06

konnigun


People also ask

How do I run a test in RSpec?

Running tests by their file or directory names is the most familiar way to run tests with RSpec. RSpec can take a file name or directory name and run the file or the contents of the directory. So you can do: rspec spec/jobs to run the tests found in the jobs directory.

Is RSpec used for unit testing?

RSpec is a unit test framework for the Ruby programming language. RSpec is different than traditional xUnit frameworks like JUnit because RSpec is a Behavior driven development tool.

What are RSpec tests?

RSpec is a testing tool for Ruby, created for behavior-driven development (BDD). It is the most frequently used testing library for Ruby in production applications. Even though it has a very rich and powerful DSL (domain-specific language), at its core it is a simple tool which you can start using rather quickly.


1 Answers

There are two approaches I would consider:

Approach 1:

Use a known value of seed in srand( seed ) in a before :each block:

before :each do   srand(67809) end 

This works across Ruby versions, and gives you control in case you want to cover particular combinations. I use this approach a lot - thinking about it, that's because the code I was testing uses rand() primarily as a data source, and only secondarily (if at all) for branching. Also it gets called a lot, so exerting call-by-call control over returned values would be counter-productive, I would end up shovelling in lots of test data that "looked random", probably generating it in the first place by calling rand()!

You may wish to call your method multiple times in at least one test scenario to ensure you have reasonable coverage of combinations.

Approach 2:

If you have branch points due to values output from rand() and your assertions are of the type "if it chooses X, then Y should happen", then it is also reasonable in the same test suite to mock out rand( n ) with something that returns the values you want to make assertions about:

 require 'mocha/setup'   Kernel.expects(:rand).with(4).returns(1)  # Now run your test of specific branch 

In essence these are both "white box" test approaches, they both require you to know that your routine uses rand() internally.

A "black box" test is much harder - you would need to assert that behaviour is statistically OK, and you would also need to accept a very wide range of possibilities since valid random behaviour could cause phantom test failures.

like image 118
Neil Slater Avatar answered Oct 23 '22 00:10

Neil Slater