Monday, June 24, 2013

Ruby: Mocking with Surrogate

Many people, most notably Martin Fowler, have written about mocking so I won't go into what it is and when to use it. (That is not to say I know the answer to both questions. It is something that I still need to research further. Maybe another post?) Eric Meyer has also written two posts on Surrogate at 8th Light blog (1, 2) but I don't think it hurts to add one more. This post assume you:
  • know Ruby
  • know Rspec
  • want another mocking mechanism for Ruby with Rspec
Let's say you have a game class that you are trying to test: 
class Game

  def initialize(rules)
    @rules = rules
  end

  def over?
    return true if @rules.winner
    return true if @rules.tied?
  end
end

This is what the Rules class looks like:
class Rules
  def initialize(board)
    @board = board
  end

  def tied?
    !winner && @board.filled?
  end

  def winner
    @board.unique_marked_values.detect {|p| win?(p)}
  end

  private
  def win?(player)
    square_sets.any? do |squares|
      squares.all? {|square| square == player}
    end
  end

  def square_sets
    @board.rows + @board.columns + @board.diagonals
  end
end
Note there are 4 methods in Rules, but only two are public, tied? and winner. Assuming you want to mock Rules because it is too complicated to set up a tied or winner situation.
  1. Create a mock folder in spec
  2. Create a mock file (you use the same name as your class file, in my case, rules.rb)
  3. In your mock file
    • Require surrogate
    • Endow the mock class
    • Define the class methods
      #game/spec/mock/rules.rb
      require 'surrogate/rspec'
      
      class MockRules
      
        Surrogate.endow(self)
      
        define(:tied?) do
          false
        end
      
        define(:winner)
      
      end
      
  4. Test if your mock is substitutable for the original class
    #game/spec/game/rules_spec.rb
    require 'game/game'
    require 'game/rules'
    require 'mock/rules'
    
    describe Game do
      it "checks if MockRules is substitutable for rules" do
        MockRules.should be_substitutable_for(Rules)
      end
    end
    
  5. Use the mock class
Let's go into a little more detail for step 3, 4, and 5.

3. Define your class method
There are three way to define your methods:
  1. One line with return type
  2.   define(:tied?) {false}
    
  3. Three lines with return type
  4.   define(:tied?) do
        false
      end
    
  5. One line with default return
  6.   define(:tied?)
    
    What this method really returns is "nil" and since nil evaluate to false as well, you can think of it as false.
If your method has a parameter, like this:
def winner(board)
   .....
end
then in your mock class, you can define the method as follow:
  define(:winner) do |value|
    value
  end
or
  define(:winner) {|value| value}

4. Test if the mock class is substitutable 
This step is important because it ensure your class has the same methods/interface as the class you are mocking. This means if I add the method def name to Rules, when I run rspec, it will fail. Or if I decide to remove def winner in Rules, running the test will fail. Again, this restrict your MockRules to have only methods defined by Rules.

5. Use the mock class
Let's say you want to test that the game is over when there is a tied. Again, this is the game over method
def over?
    return true if @rules.winner
    return true if @rules.tied?
    return false
end
For this test, you want to return true when rules.tied? is called and check to see if rules.winner is called. Here are the steps:
  1. Create a mock class with method you want to override
  2. Create the class under test
  3. Set the mock to game
  4. Call the method under test
  5. Verify expected behaviors
    • Verify over? is true
    • Verify winner was called
  it "is over when the game is tied" do
    rules = MockRules.factory(tied?: true)  #1. Create mock class with specified behavior
    game = Game.new(rules)                  #2. Create a game class 3. "Set" mock to game
    game.should be_over                     #4. Call method under test and 5. Verify expected behavior 
    rules.was asked_for :winner             #5. Verify expected behavior
  end
Note, some say that you should only test for one behavior in each test. I have not figure out where I stand on this argument, but this post is about using surrogate so it's easier for you to read if I put everything under one test. Surrogate can do a lot more. This is just a basic overview on how to use it.

Resource

Friday, June 7, 2013

The abstract factory pattern

Note: Code is in Java. 

According to OODesign, the intent of the abstract factory pattern is to "offer an interface for creating a family of related objects without specifying their classes."

So how does this relate to my story?

The factory

Let's imagine that when Gwen came to the village, they haven't figure out a system to plant vegetables yet. So everyone has to plant their own vegetables. In code, Todd class looks like this:
public class Todd {
 public Carrot getCarrot(){
  Carrot carrot = new Carrot();
  carrot.addWater(1);
  return carrot;
 }
 
 public Carrot getNoCrunchCarrot(){
  Carrot carrot = new Carrot();
  carrot.addWater(2);
  return carrot;
 }
}
Gwen class looks like this:
public class GwenSoupMaker {
 public Soup carrotSoup(){
  Carrot carrot = new Carrot();
  carrot.addWater(1);
  CarrotPieces carrot_pieces = cut(carrot);
  return cook(carrot_pieces);
 }
 
 private CarrotPieces cut(Carrot carrot) {
  return new CarrotPieces(carrot);
 }

 private Soup cook(CarrotPieces carrot) {
  return new Soup(carrot);
 }
}
See the duplication? It's just two line of code, so maybe it's ok. Now if one day, Alex says he found that if you add fertilizer, the carrot will grow faster. So everyone who grows carrot has to change their planting method by adding  fertilizer. Doesn't that sound like a lot of work? Couldn't I just tell Alex to grow the carrot and give it to me when I want it? That way only Alex needs to know about how to grow the carrot.public class Alex {
 
 public Carrot getCarrot(){
  return growCarrot(1);
 }
 
 public Carrot getNoCrunchCarrot(){
  return growCarrot(2);
 }
 
 private Carrot growCarrot(int gallonOfWater){
  Carrot carrot = new Carrot();
  carrot.addWater(gallonOfWater);
  carrot.addFertilizer();
  return carrot;  
 }
}
Now Todd class looks like this:
public class Todd {
 public Carrot getCarrot(){
  return Alex.getCarrot();
 }
 
 public Carrot getNoCrunchCarrot(){
  return Alex.getNoCrunchCarrot();
 }
}
Gwen looks like this:
public class GwenSoupMaker {
 
 public Soup carrotSoup(){
  Carrot carrot = Alex.getCarrot();
  CarrotPieces carrot_pieces = cut(carrot);
  return cook(carrot_pieces);
 }
 
 private CarrotPieces cut(Carrot carrot) {
  return new CarrotPieces(carrot);
 }

 private Soup cook(CarrotPieces carrot) {
  return new Soup(carrot);
 }
}
And if James wanted carrot, he doesn't need to know how to grow it either. He just asks Alex for it.
public class James {
 public Carrot getCarrot(){
  return Alex.getNoCrunchCarrot();
 }
}
In term of code, Alex is our factory. He is the only one with knowledge on how to grow carrot. If growing no crunch carrot needs 3 gallon of water, only Alex needs to know.

The abstract factory

Remember when Gwen started to do super well with her store? She had to go to Todd several times to buy zucchini. Every time she needs zucchini, she has to find Todd. But, Todd is busy man. To make it easier for customer to buy zucchini, he put up a stand in front of his house so his son or his wife can sell the zucchini when Todd is not available. That way, when Gwen needs zucchini, she goes to the stand instead of asking Todd.

In code term, that just mean Todd has an interface and Gwen just talk to the interface when she wants a zucchini. So Gwen class looks like this:
import java.util.List;

public class GwenSoupMaker {
 ZucchiniFarmer zucchiniFarmer;
 public GwenSoupMaker(ZucchiniFarmer farmer){
  zucchiniFarmer = farmer;
 }
 
 public Soup zucchiniSoup(){
  List zucchinis = zucchiniFarmer.buy(3);
  return cook(zucchinis);
 }
 
 private Soup cook(List zucchinis) {
  return new Soup(zucchinis);
 }

Todd:
import java.util.ArrayList;
import java.util.List;

public class Todd implements ZucchiniFarmer{
 public List buy(int amount) {
  List zucchinis = new ArrayList();
  for (int i = 0; i < amount; i++){
   zucchinis.add(new Zucchini(1));
  }
  return zucchinis;
 }
}
Zucchini farmers:
import java.util.List;


public interface ZucchiniFarmer {
 public List buy(int amount);
}

Thursday, June 6, 2013

Design pattern story - the beginning

I've been struggling to explain design pattern that I feel is easier to understand. So after reading "Storytelling for Software Professionals" by Arjen Uittenbogaard on May/June issue of IEEE Software, I decided to give it a try and explain design pattern in term of a story. This is a story I made up to serve as the base to explain design patterns.

----------------------------------------------------------------------------

Once upon a time, there was a farmer named Todd. Todd loves zucchini, so he spent all his time figuring out how to plant the perfect zucchini. After years of trial and error, he finally found a way to plant the perfect zucchini. He invited everyone in the village over to try his perfect zucchini. They were all amazed at how delicious they were! Everyone asked Todd to show them how he did it. "The secret," Todd said, "is to water the plant before sunrise." Everyone thanked Todd and went home to plant their own zucchini.

One day, Todd met Mary, a beautiful girl from a nearby village. The two fell in love and got married. Seeing the empty space on Todd's land, Mary asked if he can plant carrot because it's her favorite vegetable. As newlyweds, Todd was still in love. So he happily went to Alexander, the best carrot farmer and asked for instructions. "The secret," Alex said, "is to water it at 7AM and 6 PM to ensure the carrot has enough water to grow." Todd thanked Alex and happily went home. After months of hard work, Todd had a whole lot full of perfect carrots. It was sweet and crunchy, just as he expected. His wife was so happy. They hug, they kissed, and the next thing they know, they had a baby.

When the baby was born, Todd tried to feed the baby with his perfect carrot. But the baby couldn't eat it. It was too crunchy.

"You should ask Alex on how to plant baby carrot that has no crunch," his wife advised.

So Todd went back to Alex and explained his problem.

"If you want the carrot to be less crunchy, water it more and pull it up earlier," Alex, the carrot farmer said.

Todd did as instructed. And surely, he had carrot with no crunch. As the baby grow older, Mary wanted to add a little crunch to the carrot. But carrot takes months to grow. By the time Todd got the carrot to have a little crunch, the baby was ready for the regular carrot. Plus, keeping track of when to water the plant and how much water for which row becomes a little too much.

Feeling frustrated, Todd went to Alex, the carrot farmer and complained about the situation. Alex nodded understandingly, as if he had heard it before.

"Listen," Alex said. "James, my neighbor is also having a problem similar to yours. He grows the best potatoes. So I told him, if he grows me some potatoes, I'll grow the carrot for him. I can also do that for you if you grow me some of your zucchini. That way you don't have to worry about growing carrot."

"What a great idea!" Todd exclaimed. So next year, Alex grew only carrot and Todd only grew zucchini. Whenever Todd needed carrot, he goes to Alex and tell Alex the type of crunch he wants and Alex would pull it from his garden.

One day, Gwen, Mary's sister, came to visit the couple. She saw how beautiful and prosperous the village was and decided to make it her new home. Now Gwen was a very talented chef. She decided to open a soup shop to make a living. Instead of growing her own vegetables, Gwen went to Todd for zucchini, Alex for carrot, and James for potato. Because Gwen didn't have to worry about growing vegetables, she could focus on perfecting her soup. Her zucchini soup became so popular that it attracted many visitors from neighboring villages. This in turn increased her demand for Todd's zucchini. But Todd was often busy with the farm, so he didn't have time to sell the zucchini.

"Why don't we open a zucchini stand?" Mary wisely suggested. "That way, when you're busy on the farm, our son or I can sell it. The customer never have to go look for you when they want to buy zucchini."

"Great idea. Let's set up a zucchini stand in front of our house," said Todd.

So the couple set up a zucchini stand. Whenever Gwen needed zucchini, she went to Todd's stand. She didn't have to look for Todd nor did she care who is selling the zucchini. The zucchini stand did so well, Todd and Mary saved enough money to build a bigger house and send their son to school..................eh and they live happily ever after.

Wednesday, June 5, 2013

Deploying Rail with Heroku

One of my task this week is to learn Rails so I can build a web based Tic Tac Toe game. I followed the Ruby on Rails Tutorial but I was having trouble deploying my application on Heroku (i.e. section 1.4.2 in the book). Whenever I tried to do this:
git push heroku master
I get this:
Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights and the repository exists.

To solve this problem, I read how to manage your keys. I can't say I have the right answer, but this works for me.
  1. Make sure you have only one public key on Heroku (I'm not saying 2+ won't work. I'm saying it didn't work for me.) I'm doing this all in the command line.
    1. Type "heroku keys" to see what keys Heroku has for your profile
    2. Type "heroku keys:remove key_name" to remove the key you don't want
  2. Make sure the key you have is the same key on github
    1. To add the key "heroku add ~/.ssh/key_name.pub"

Note: You may need to login to heroku to do this. In order to log in, type "heroku login" then type your credentials.

If all that doesn't work, try to create a config file in your ssh folder. Your config file should look like this:
Host heroku.com
Hostname heroku.com
Port 22
IdentitiesOnly yes
IdentityFile ~/.ssh/your_key_name
TCPKeepAlive yes
User your_email
Resource:
  1. Managing your keys in Heroku
  2. Stackoverflow answer

Tuesday, June 4, 2013

Running slow test (with rake)

Situation: I have a test file that takes a really long time to run. What do I do?

Propose solution: Don't test the file? Of course not! The test file is there to ensure I didn't break anything.  If I don't test it, how do I know my code is working as intended? How do I know the new code didn't break existing code? 

Real solution: Separate out the tests. 

Example: I am working on a TicTacToe game. The game has a computer player that uses minimax to compute the next step. This algorithm takes a long time to calculate when the board has a lot of empty squares. So whenever I add new code and run rspec, it takes a really long time to run, even though the new code has nothing to do with the computer logic. So what I really want is simple command to:
  1. run all test
  2. run slow test
  3. run all test excluding the slow test
If I separated it out like that, I can run most of my test regularly and the slow one before I check in or when I actually change the file. How do I do this? Use Rake. 

Rake is a build tool created by Jim Weirich for Ruby. There are many articles on Rake, including Martin Fowler's detailed explanation. Most didn't really explained what I wanted, so I asked other apprentices for help. Thankful Taka is knowledgable on the subject and offered to help :)

Steps:

  1. Install rake "gem install rake"
  2. Create a file in your project directory call "Rakefile"
  3. Add the tasks to your rake file. This is what my rake file looks like: 
require 'rspec/core/rake_task'

RSpec::Core::RakeTask.new(:default)

RSpec::Core::RakeTask.new(:slow_test) do |t|
  t.rspec_opts = "--tag slow_test"
end

RSpec::Core::RakeTask.new(:test) do |t|
  t.rspec_opts = "--tag ~slow_test"
end
What the file say?
  • Line 3 says, run all tests as the default. 
    • Command: rake
  • Line 5 created a new task called "slow_test" which runs all the test with the tag "slow test" (more on this later). Note that you specify the task name with ":task_name".
    • Command: rake slow_test
  • Line 9 created a new task called "test" which runs all the test excluding the one with the tag "slow_test".
    • Command: rake test
In addition, I can also create a command to run my game. Normally, I would type in "ruby bin/tictactoe", but I can make a shorter command using rake. I called my task play, so I can just type "rake play" and it will start the game for me. Cool eh?
task :play do
  ruby "bin/tic_tac_toe"
end

Tagging test files

I will need to do more research on the topic, but for this rake file to work, I need to add this to my computer test file.
Normal
describe TicTacToe::Player::Computer do
end
Tagged.
Note Taka added a comma after the class under test, then the tag.
describe TicTacToe::Player::Computer, :slow_test => true do
end