nskins / goby

Command-line role-playing game framework

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Refactor tests to use `let` instead of instance variables

jamesball27 opened this issue · comments

I noticed that most of the tests use a before action to assign instance variables that are used throughout the tests. This is not great for a couple of reasons:

  1. Instance variables are created wherever they are referenced, so you are more prone to typos.
  2. Oftentimes objects are being instantiated that are not being used in all of the tests, which is unnecessary.

I suggest refactoring to use let, this will clean up the code, protect against inadvertent typos, and speed up run time (let is lazy-loaded so you won't be instantiating every object for every test).

For example, the Escape Spec would now look like this:

#spec/goby/battle/escape_spec.rb

RSpec.describe Goby::Escape do
  let(:player) { Player.new }
  let(:monster) { Monster.new }
  let(:escape) { Escape.new }

  context "constructor" do
    it "has an appropriate default name" do
      expect(escape.name).to eq "Escape"
    end
  end

  context "run" do
    # The purpose of this test is to run the code without error.
    it "should return a usable result" do
      # Exercise both branches of this function w/ high probability.
      20.times do
        escape.run(player, monster)
        expect(player.escaped).to_not be nil
      end
    end
  end

end

This is a pretty big refactor, I'm happy to take it on if you think it's worth it.

@jamesball27 - Yes, that would help a lot! Do you know if we could distinguish between before(:all) and before(:each) using the let statements? I think there are some cases in the test suite when one or the other is specifically needed. I believe there are a few cases when I use before(:all) to carry over the state from the previous test (I know - bad unit testing practice!).

Cool, I'll take a crack at this then.

Basically the let statements create a variable that is available to everything within the block it is defined in. So if you define them in the outermost scope, all of your tests have access to them. If you need a more specific instance in any given context block, you can use another let statement in that scope.