RSpec. How to color the piped or redirected output? - ruby

In versions of RSpec before 2.0 I could pipe the color output to less or redirect it to a file. In order to do it I simply have to set the RSPEC_COLOR environment variable to true. However, in the new main version of the framework this variable has stopped to define the output type (color or monchrome). Is there any way to pipe or redirect the color in RSpec 2.0 and higher?
Thanks.
Debian GNU/Linux 5.0.7;
Ruby 1.9.2;
RSpec 2.4.0.
Updated
I found the answer by myself.
One should use the tty configuration option to achieve the effect.
Here's the example:
# spec/spec_helper.rb
RSpec.configure do |config|
config.tty = true
end

The answer in the question is the correct one:
# spec/spec_helper.rb
RSpec.configure do |config|
config.tty = true
end
Then rspec | grep --color="never" something keeps the coloring.

By looking at the sources, it seems that the color_enabled configuration option is now in the Configuration module of RSpec. However, if the output is not done to a tty, color is disabled.
My suggestion would be to set color_enabled = true and to monkey patch the RSpec Configuration module so that is works even when not outputting to a tty:
module RSpec
module Core
class Configuration
def color_enabled
true
end
end
end
end
This is not the nicest way, though. This is also untested and I think that monkey patching rspec is not the easiest thing to do because usually tests are run via the dedicated command line tool.
Maybe you could open a bug report to the maintainer and ask for a force_color_enabled option ? It would probably be very quick to implement...
Good Luck and Happy Coding !

It's as simple as:
# spec/spec_helper.rb
RSpec.configure do |config|
config.color_enabled = true
end

Related

Customising IRB console for gem

I'd like to extend the default console application that is built as standard with bundle gem by applying some of the IRB config options.
Looking at the documentation, I can see that it should be possible for instance to change the prompt, and this works fine on an interactive session. For example I can play with the displayed prompt like this:
2.1.4 :001 > conf.prompt_mode=:SIMPLE
=> :SIMPLE
>>
?> conf.prompt_mode=:DEFAULT
=> :DEFAULT
irb(main):004:0>
However, I cannot find how to translate this into syntax for use in the console app. For example this script:
require 'irb'
IRB.conf[:PROMPT_MODE] = :SIMPLE
IRB.start
Just starts with the generic configured prompt:
2.1.4 :001 >
I have spent some time trying to find an example use of IRB for a custom repl without loading global defaults, but not found anything I can copy from.
I can see that the undocumented method IRB.setup has something to do with this, it is setting all the config somehow. Is my only option to write my own version of IRB.start that applies my desired config after calling IRB.setup, or is there support for what I want to do built-in but not documented in standard location?
E.g. the following works, but I feel it's a bit heavy handed extending IRB module this way (and also prone to failing if IRB internals change).
require 'irb'
def IRB.custom_start custom_conf = {}
STDOUT.sync = true
IRB.setup(nil)
custom_conf.each do |k,v|
IRB.conf[k] = v
end
if #CONF[:SCRIPT]
irb = IRB::Irb.new(nil, #CONF[:SCRIPT])
else
irb = IRB::Irb.new
end
#CONF[:IRB_RC].call(irb.context) if #CONF[:IRB_RC]
#CONF[:MAIN_CONTEXT] = irb.context
trap("SIGINT") do
irb.signal_handle
end
begin
catch(:IRB_EXIT) do
irb.eval_input
end
ensure
irb_at_exit
end
end
IRB.custom_start :PROMPT_MODE => :SIMPLE
You can apply custom configurations in two ways.
The first one is to use irbrc file. It may be tricky in building console application (calling IRB.start from the ruby file instead of irb from the console).
The second one is the approach that you have described in the post. You can write your own IRB::start method based on the original one. There are exactly the same potential issues as in using undocumented API - it can break in the future with newer versions of irb.
You should think if you really need to build a console application on the top of irb. For example you can solve this problem using Pry. It allows to define configuration before starting interactive session.
require 'irb'
IRB.conf[:PROMPT_MODE] = :SIMPLE
IRB.start
The approach above doesn't work because conf[:PROMPT_MODE] gets over-riden in a method called IRB.init_config here
When IRB.start is called, it calls IRB.setup which in turn calls the method IRB.init_config -- which over-rides conf[:PROMPT_MODE] setting.
Here is one approach which solves the problem (relies on internal knowledge of the implementation).
require 'irb'
module IRB
singleton_class.send(:alias_method, :old_setup, :setup)
def IRB.setup(ap_path)
IRB.old_setup(ap_path)
conf[:PROMPT_MODE] = :SIMPLE
end
end
IRB.start

How to specify the RSpec "syntax" parameter on the command line?

We have a shell script which launches our RSpec tests. It looks something like this:
args+=(
"--format" "html"
"--out" "$to_dir/index.html"
)
"$rspec_dir/rspec" "${args[#]}" "$tests_to_run"
exit $?
When trying to upgrade RSpec, I'm getting an error that the :should syntax is deprecated, and we need to explicitly enable it like so: How to avoid deprecation warning for stub_chain in RSpec 3.0?
However, since we're not using Rake, I need to figure out a way to do this when launching rspec through the command line. But when I try adjusting the command line options like so:
./rspec --format "html" --out "index.html" --syntax ":should"
It says --syntax is not a valid option. How can I enable this deprecated syntax while invoking rspec directly through the command line?
(We can't use Rake because our internal build tools don't support it. That's why I need to find out how to do this through the command line.)
You can't configure RSpec expectations and mocks syntax on the command line. Edit your project's spec/spec_helper.rb to include the following:
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.syntax = [:should, :expect]
end
config.mock_with :rspec do |mocks|
mocks.syntax = [:should, :expect]
end
end
After you're upgraded, you'll probably want to change all of your examples to use the new syntax (probably with transpec) and then disable the :should syntax.
More here https://relishapp.com/rspec/rspec-expectations/docs/syntax-configuration and here https://relishapp.com/rspec/rspec-mocks/docs/old-syntax/stub

How to define a simple global variable in an rspec test that can be accesed by helper functions

I cant figure out how to use a simple global variable in an rspec test. It seems like such a trivial feature but after much goggleing I havent been able to find a solution.
I want a variable that can be accessed/changed throughout the main spec file and from functions in helper spec files.
Here is what I have so far:
require_relative 'spec_helper.rb'
require_relative 'helpers.rb'
let(:concept0) { '' }
describe 'ICE Testing' do
describe 'step1' do
it "Populates suggestions correctly" do
concept0 = "tg"
selectConcept() #in helper file. Sets concept0 to "First Concept"
puts concept0 #echos tg?? Should echo "First Concept"
end
end
.
#helpers.rb
def selectConcept
concept0 = "First Concept"
end
Can someone point out what I am missing or if using "let" is totally the wrong method?
Consider using a global before hook with an instance variable: http://www.rubydoc.info/github/rspec/rspec-core/RSpec/Core/Configuration
In your spec_helper.rb file:
RSpec.configure do |config|
config.before(:example) { #concept0 = 'value' }
end
Then #concept0 will be set in your examples (my_example_spec.rb):
RSpec.describe MyExample do
it { expect(#concept0).to eql('value') } # This code will pass
end
It turns out the easiest way is to use a $ sign to indicate a global variable.
See Preserve variable in cucumber?
This is an old thread, but i had this question today. I just needed to define a long string to stub out a command that is in multiple files as:
# in each spec file that needed it
let(:date_check) do
<<~PWSH.strip
# lots of powershell code
PWSH
end
# in any context in that file (or a shared context)
before(:each) do
stub_command(date_check).and_return(false)
end
Searched, Stack Overflow, etc, landed on this: Note the usage of the variable doesn't change at all! (Assumes all specs require 'spec_helper')
# in spec_helper.rb
def date_check
<<~PWSH.strip
# lots of powershell code
PWSH
end
# in any context in any spec file
before(:each) do
stub_command(date_check).and_return(false)
end
I suggest you define the variable in the helper file, where it can be used by other helper code, and can be accessed from your tests.
For my project, I wanted to keep all the setup stuff in spec_helper.rb, and use those settings, plus any custom variables and methods in the tests. The following, modified from the RSpec-core 3.10 docs, is not Rails-specific.
Create a new setting for RSpec.configure called my_variable, and give it a value, like this:
# spec/spec_helper.rb
RSpec.configure do |config|
config.add_setting :my_variable
config.my_variable = "Value of my_variable"
end
Access settings as a new read-only property in RSpec.configuration from your test:
# spec/my_spec.rb
RSpec.describe(MyModule) do
it "creates an instance of something" do
my_instance = MyModule::MyClass.new(RSpec.configuration.my_variable)
end
end

How do I globally configure RSpec to keep the '--color' and '--format specdoc' options turned on

How do I set global configuration for RSpec in Ubuntu.
Specifically so, --color and --format specdoc stay turned on, across all my projects (ie every time I run rspec anywhere).
As you can see in the docs here, the intended use is creating ~/.rspec and in it putting your options, such as --color.
To quickly create an ~/.rspec file with the --color option, just run:
echo '--color' >> ~/.rspec
One can also use a spec_helper.rb file in all projects. The file should include the following:
RSpec.configure do |config|
# Use color in STDOUT
config.color = true
# Use color not only in STDOUT but also in pagers and files
config.tty = true
# Use the specified formatter
config.formatter = :documentation # :progress, :html,
# :json, CustomFormatterClass
end
Any example file must require the helper to be able to use that options.
In your spec_helper.rb file, include the following option:
RSpec.configure do |config|
config.color_enabled = true
end
You then must require in each *_spec.rb file that should use that option.
If you use rake to run rspec tests then you can edit spec/spec.opts
http://rspec.info/rails/runners.html
Or simply add alias spec=spec --color --format specdoc to your ~/.bashrc file like me.
One thing to be aware of is the impact of the different ways of running RSpec.
I was trying to turn on the option with the following code in spec/spec_helper.rb -
Rspec.configure do |config|
config.tty = $stdout.tty?
end
calling the 'rspec' binary directly - or as 'bundle exec rspec' and checking $stdout.tty? will return true.
invoking the 'rake spec' task - or as 'bundle exec rake spec' - Rake will invoke rspec in a separate process, and $stdout.tty? will return false.
In the end I used the ~/.rspec option, with just --tty as its contents. Works well for me and keeps our CI server output clean.

How do you run a specific test with test/spec (not a specific file, but a spec within a given file)?

With Test::Unit, I can run:
ruby path/to/test.rb --name=test_name_that_i_want_to_run
Thus far, I have not been able to figure out how to do this with test/spec specifications. I am wondering if the way that specifications are automatically named does not allow me to do something like this.
Take the following spec for example:
require 'rubygems'
require 'spec'
describe 'tests' do
it 'should be true' do
1.should == 1
end
it 'should be false' do
1.should_not == 2
end
end
You can execute a single spec by using the -e flag and providing the portion specified by the it block. e.g. ruby my_spec.rb -e 'should be false'
After contacting the gem maintainer, Christian Neukirchen, I found out how to do this, so I am documenting it here for future reference.
specrb path/to/test.rb --name ".*should behave this way.*"
I needed to use the specrb test runner, an extended version Test::Unit's test runner, rather than just the ruby command.
You can also do this with the ruby command:
ruby path/to/test.rb -n "/should behave this way/"

Resources