Re: Questions about testing a module method that randomly creates stuff from list

---- David C. [email protected] wrote:

On Jul 15, 2010, at 12:18 PM, Greg D. wrote:

This sounds like a long, procedural method. Can it be broken down any further (i.e. delegating more of its work to other methods)?

Yes, it is. The sub methods are the broken down part and not overridden
super methods like I guess I made it sound based on your answers below.

object.super_method

If the real sub_method sets any internal state (i.e. assigns values to instance variables), then this won’t work at all.

Well, they don’t assign instance variables. They are really just
methods handling conditions of the randomness in the parent method.

It’s much easier to control state in an example, rather than inspect state and set different expectations based on it. Consider a simulation of a game that involves a die:

die = double(‘die’)
die.stub(:roll).and_return(2)

board.set(piece).at(30)
board.roll(die)
board.square_at(32).should contain(piece)

Make sense?

Funny you used die when this problem is for a game.

Yes, I can stub out the conditions that each child method handles. This
procedural method has grown because of the permutations increase
exponentially with more data. But, the conditions to handle (defined in
the child methods) have become finite and all I have to do is test those
with mocks and stubs.

I know I put the cart before the horse in TDD/BDD, but this was a very
difficult problem to solve:
Create a random tournament layout of unique teams of players where a
team is matched with another random team of different players and every
player plays on teams made up of all the other players to complete the
tournament. This way you find the best individual player. Example of
this would be euchre, bridge, other team playing card games, etc. But
not limited to card games and not limited to 2 man teams. Also, it
must allow for uneven number of players in the tournament. i.e. players
would have byes throughout the tournament and those byes would be evenly
distributed throughout the tournament. For example: a tournament of 2
players per team and 2 teams per match made up of say 15 players would
have all players have had the same number of byes at the end of every
5th round.

I actually wrote this 20 years ago in ANSI C. Now I have written it in
ruby. It has been just about as hard to do, but less lines of code,
cleaner and runs faster mainly because in the C code evaluated each team
as it was searching for a team to place into a round where is the ruby
code it was simple to remove and shrink the possible opponents with one
line of code. :slight_smile: So, while the C code would take maybe hours to figure
out a layout of 200+ euchre players. The ruby code does it in a few
minutes on the same machine. Not that you would every have that large
of a tournament. Just out of curiosity, I tried the a very large size
tournament to compare the timing.

I do have one more question, how would you write a test for a recursive
method? I have a couple of those too.

Thanks for the ideas,

GregD

On Jul 16, 2010, at 11:38 AM, Greg D. wrote:

If the real sub_method sets any internal state (i.e. assigns values to instance variables), then this won’t work at all.
board.roll(die)
board.square_at(32).should contain(piece)

Make sense?

Funny you used die when this problem is for a game.

Yes, I can stub out the conditions that each child method handles. This procedural method has grown because of the permutations increase exponentially with more data. But, the conditions to handle (defined in the child methods) have become finite and all I have to do is test those with mocks and stubs.

Sounds like you’ve got a lot of conditional logic that might be better
expressed with polymorphism? I’d need to see the method, but if you
expressed the conditions in different objects rather than child methods,
you might end up with smaller bits that are easier to test in isolation.

I know I put the cart before the horse in TDD/BDD, but this was a very difficult problem to solve:

We all put the cart before the horse from time to time, but your “but”
suggests that you believe the TDD is only for easy problems. That
couldn’t be farther from the truth. The whole point is to start off with
a small bit functionality, drive it out with tests, and slowly build up
the complexity.

Create a random tournament layout of unique teams of players where a team is matched with another random team of different players and every player plays on teams made up of all the other players to complete the tournament. This way you find the best individual player. Example of this would be euchre, bridge, other team playing card games, etc. But not limited to card games and not limited to 2 man teams. Also, it must allow for uneven number of players in the tournament. i.e. players would have byes throughout the tournament and those byes would be evenly distributed throughout the tournament. For example: a tournament of 2 players per team and 2 teams per match made up of say 15 players would have all players have had the same number of byes at the end of every 5th round.

I actually wrote this 20 years ago in ANSI C. Now I have written it in ruby. It has been just about as hard to do, but less lines of code, cleaner and runs faster mainly because in the C code evaluated each team as it was searching for a team to place into a round where is the ruby code it was simple to remove and shrink the possible opponents with one line of code. :slight_smile: So, while the C code would take maybe hours to figure out a layout of 200+ euchre players. The ruby code does it in a few minutes on the same machine. Not that you would every have that large of a tournament. Just out of curiosity, I tried the a very large size tournament to compare the timing.

I do have one more question, how would you write a test for a recursive method? I have a couple of those too.

I’ve never found a better way than to treat it as a black box and
specify how it should respond to different inputs.

HTH,
David