Question

I have a number of specs, which i wish to use in a Rails view (v3.2.15).

I'm using the rspec-rails gem v2.14.0, and the code i run is below.

This code used to work on v2.11.4 of the gem and I can see HtmlFormatter has now had some of its code split out into HtmlPrinter, which i imagine has something to do with the error. How are you meant to use HtmlFormatter? I can't find any documentation beyond the source code... What am i doing wrong below?

  class RSpecRunner
    attr_accessor :summary, :html, :documentation
    SpecPath = "system_checks/**/*_spec.rb"
    DataChecks = "data_checks/**/*_spec.rb"

    def initialize(path)
      @html = RSpec::Core::Formatters::HtmlFormatter.new(nil)
      @documentation = RSpec::Core::Formatters::DocumentationFormatter.new(nil)
    end

    def run!
      RSpec::world.reset
      Dir[@spec_path].each { |f| load f }

      @html = RSpec::Core::Formatters::HtmlFormatter.new(nil)
      reporter = RSpec::Core::Reporter.new(@html)

      RSpec::world.example_groups.each do |example_group|
        example_group.run(reporter)
      end
    end
  end

Controller

@sys_check = RSpecRunner.new(RSpecRunner::SystemChecksPath)
@sys_check.run!

View

@sys_check.html.output.string

Error

NoMethodError: private method `puts' called for nil:NilClass
    from /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.14.7/lib/rspec/core/formatters/html_printer.rb:23:in `print_example_group_start'
    from /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.14.7/lib/rspec/core/formatters/html_formatter.rb:50:in `example_group_started'
    from /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.14.7/lib/rspec/core/reporter.rb:127:in `block in notify'
    from /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.14.7/lib/rspec/core/reporter.rb:126:in `each'
    from /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.14.7/lib/rspec/core/reporter.rb:126:in `notify'
    from /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.14.7/lib/rspec/core/reporter.rb:74:in `example_group_started'
    from /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.14.7/lib/rspec/core/example_group.rb:367:in `run'
    from (irb):11:in `block in irb_binding'
    from (irb):10:in `each'
    from (irb):10

Thanks

Was it helpful?

Solution

The HtmlFormatter wants a way to output stuff. Give it STDOUT:

@html = RSpec::Core::Formatters::HtmlFormatter.new(STDOUT)

If you want the output to go to a file however, such as an HTML file, give it a file handle:

fh = File.open('path/to/html_output/rspec-html-output.html', 'w')
@html = RSpec::Core::Formatters::HtmlFormatter.new(fh)

Now you'll have a nice little html file of rspec's formatted output.

Edit: Whatever you pass to RSpec::Core::Formatters::HtmlFormatter.new needs to respond to puts and flush.

Since you want to save the output to accessors you can define those methods on your own custom classes that will save the output to the appropriate accessors :html and :documentation:

class HTMLOutput
  def initialize(rspec_runner)
    @rspec_runner = rspec_runner
  end

  def puts(html)
    @rspec_runner.html ||= ""
    @rspec_runner.html << html
  end

  def flush; end
end

class DocOutput
  def initialize(rspec_runner)
    @rspec_runner = rspec_runner
  end

  def puts(html)
    @rspec_runner.documentation ||= ""
    @rspec_runner.documentation << html
  end

  def flush; end
end

class RSpecRunner
  def initialize(path)
    # I assumed you wanted to save the output of the formatter to the 
    # accessors :html and :documentation but you were already assigning
    # the formatters to these accessors via @html etc. Make new instance vars
    # for these and use the accessors just for the output.
    # By instantiating these output classes and passing in self they will be able
    # to save the output to the :html, :documentation accessors.
    @html_formatter = RSpec::Core::Formatters::HtmlFormatter.new(HTMLOutput.new(self))
    @documentation_formatter = RSpec::Core::Formatters::DocumentationFormatter.new(DocOutput.new(self))
  end

  ... rest of your code ...
end

Finally, in your runner's run! method you don't need to instantiate this guy again:

@html = RSpec::Core::Formatters::HtmlFormatter.new(nil)

Hope that helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top