How do I execute a single test using Ruby test/unit? - ruby

Instead of running all the test cases automatically, is there any way to execute a single test under ruby test/unit framework. I know I can achieve that by using Rake but I am not ready to switch to rake at this moment.
ruby unit_test.rb #this will run all the test case
ruby unit_test.rb test1 #this will only run test1

you can pass the -n option on the command line to run a single test:
ruby my_test.rb -n test_my_method
where 'test_my_method' is the name of the test method you would like to run.

If you look for a non-shell solution, you could define a TestSuite.
Example:
gem 'test-unit'
require 'test/unit'
require 'test/unit/ui/console/testrunner'
#~ require './demo' #Load the TestCases
# >>>>>>>>>>This is your test file demo.rb
class MyTest < Test::Unit::TestCase
def test_1()
assert_equal( 2, 1+1)
assert_equal( 2, 4/2)
assert_equal( 1, 3/2)
assert_equal( 1.5, 3/2.0)
end
end
# >>>>>>>>>>End of your test file
#create a new empty TestSuite, giving it a name
my_tests = Test::Unit::TestSuite.new("My Special Tests")
my_tests << MyTest.new('test_1')#calls MyTest#test_1
#run the suite
Test::Unit::UI::Console::TestRunner.run(my_tests)
In real life, the test class MyTest will be loaded from the original test file.

Related

How to write a Ruby (Minitest) unit test that fails if I don't have the correct require statements?

I have this test:
require 'minitest/autorun'
require 'minitest/color'
require_relative '../lib/util/input_file'
class TestInputFile < Minitest::Test
def setup
#input_path = Pathname.new("/path/to/inputs")
end
def test_default_input_file
input_file = Util::InputFile.new(1)
expected_path = #input_path.join('input01.txt')
assert_equal(expected_path, input_file.abspath)
end
# more tests follow
end
for this code:
module Util
class InputFile
def initialize(num)
#num = num
#input_dir = Pathname.new("/path/to/inputs")
end
def abspath
basename = 'input'
return #input_dir.join(format('%s%02d.txt', basename, #num))
end
end
end
When I run this with rake test, everything passes as expected; however, when I call it from my actual main script, it chokes with uninitialized constant Util::InputFile::Pathname (NameError). When I add require 'pathname' at the top of lib/util/input_file.rb, everything is fine.
Why does the unit test not fail in the same way, and how can I refactor it such that it will fail unless I have the correct require statement in the production code?
EDIT: Rakefile is as follows:
require 'minitest/test_task'
Minitest::TestTask.create do |t|
t.test_globs = ['test/**/test*.rb']
end
To run tests separately use rake test:isolated instead of rake test.
https://github.com/minitest/minitest#rake-tasks-
It seems like one of your other tests gets Pathname loaded.
How does your Rakefile look and doesn't it get pathname required? It can explain why your test (started with rake test) goes well.
And why don't you want to require pathname at the top of lib/util/input_file.rb?

Webdriver with Ruby and Minitest. Share test cases code between test suites

I need to share test code between a set of suites, but the thing is that I don't know how to define the test cases in the separate file so every other test suite can use the same test cases.
This is a sample of my files:
test_api.rb:
require_relative 'test_helper'
require 'rubygems'
require 'minitest/spec'
require 'minitest/autorun'
#require 'minitest/hell'
require 'uri'
require 'net/http'
require 'mysql2'
require 'json'
require 'digest/sha1'
require_relative 'cases_api_shared.rb'
class API_pc_qubit
#parallelize_me!
def setup
### DEFINITIONS
### URL
ENV['ws_url'] = 'http://.../'
### DATA DEFINITION (USERNAME, PASSWORD, ETC)
ENV['username'] = 'user'
ENV['password'] = 'pass'
### DEVICE = PC
ENV['APK_ID'] = "1"
ENV['APK_SECRET'] = "secret"
end
def test_user_create
# User registration test case
case_user_create
end
def test_user_login
# User login test case
case_user_login
end
def test_content_search
# Search for content test case
case_content_search
end
def test_utils_channels
# channels test case
case_utils_channels
end
def test_content_list
# Content list case
case_content_list
end
def test_user_modify
# Change user data test case
case_user_modify
end
def test_user_change_suscription
# Change user suscription test case
case_user_change_suscription
end
def test_user_favorite
# User profiles test case
case_user_favorite
end
def test_commercial_buyandplay
# Change user login password test case
case_commercial_buyandplay
end
#def test_content_status
#
# # Test content status currenttime test case
#
# case_content_status
#end
def teardown
end
end
And this is a sample of the cases_api_share.rb file:
require_relative 'obj_api_shared.rb'
def case_user_create
# User registration test case
case code...
end
def case_user_login
# User login test case
another test code...
end
And but when I run the suite, it didn't run the code in 'cases_api_share':
ruby tests/test_api.rb
Started with run options --seed 30622
Finished in 0.00055s
0 tests, 0 assertions, 0 failures, 0 errors, 0 skips
This is probably a duplicated. See here.
Based on that, here is an example.
If you want to group test, there is a easy way, just use autorun in the test files and require the test files in the suit.
#suit1.rb
require './test1.rb'
#suit2.rb
require './test1.rb'
require './test2.rb'
#test1.rb
require 'minitest/autorun'
class TestOne < MiniTest::Unit::TestCase
def test_one
assert_equal 1, 1
end
end
#test2.rb
require 'minitest/autorun'
class TestTwo < MiniTest::Unit::TestCase
def test_two
assert_equal 2, 2
end
end
You can run the suit or each test individually:
ruby suit1.rb
ruby suit2.rb
ruby test1.rb
ruby test2.rb
You can get the example code here

With Test::Unit, how can I run a bit of code before all tests (but not each test)?

In my test app, which uses test::unit, I need to start by pulling a bunch of data from various sources. I'd like to only do this once - the data is only read, not written, and doesn't change between tests, and the loading (and error checking for the loading), takes some time.
There are values that I DO want reset every time, and those are easy enough, but what if I want persistant accessible values? What's the best way to do this?
I'm especially interested in solutions that would let my push those assignments to some module that can be included in all my tests, since they all need access to this data.
Why do you need it inside the test? You could define it gloabl:
gem 'test-unit'#, '>= 2.1.1' #startup
require 'test/unit'
GLOBAL_DATA = 11
class My_Tests < Test::Unit::TestCase
def test_1()
puts "Testing startup 1"
assert_equal(11, GLOBAL_DATA)
end
end
GLOBAL_DATA could be a (singleton)-class (respective an instance).
If you have only one testclass, you may use TestCase.startup:
gem 'test-unit'#, '>= 2.1.1' #startup
require 'test/unit'
class My_Tests < Test::Unit::TestCase
def self.startup
puts "Define global_data "
##global_data = 11
end
def test_1()
puts "Testing 1"
assert_equal(11, ##global_data = 11)
end
def test_2()
puts "Testing 2"
assert_equal(11, ##global_data = 11)
end
end
You can just put them at the top of the class. They will get executed, and then your tests will get executed.
You could do this in the setup method:
def setup
if !defined?(##initial_data)
# Whatever you need to do to get your initial data
##initial_data = foo
end
#other_data = bar
end

Before/After Suite when using Ruby MiniTest

Is there an alternative to RSpec's before(:suite) and after(:suite) in MiniTest?
I suspect that a custom test runner is in order, however I cannot imagine it is not a common requirement, so somebody has probably implemented in. :-)
There are setup() and teardown() methods available. The documentation also lists before() and after() as being available.
Edit: Are you looking to run something before each test or before or after the whole suite is finished?
As noted above in Caley's answer and comments, MiniTest::Unit contains the function after_tests. There is no before_tests or equivalent, but any code in your minitest_helper.rb file should be run before the test suite, so that will do the office of such a function.
Caveat: Still relatively new at Ruby, and very new at Minitest, so if I'm wrong, please correct me! :-)
To get this to work with the current version of Minitest (5.0.6) you need to require 'minitest' and use Minitest.after_run { ... }.
warn "MiniTest::Unit.after_tests is now Minitest.after_run. ..."
https://github.com/seattlerb/minitest/blob/master/lib/minitest.rb
https://github.com/seattlerb/minitest/blob/master/lib/minitest/unit.rb
To run code before each test, use before. You're operating here in the context of an instance, possibly of a class generated implicitly by describe, so instance variables set in before are accessible in each test (e.g. inside an it block).
To run code before all tests, simply wrap the tests in a class, a subclass of MiniTest::Spec or whatever; now, before the tests themselves, you can create a class or module, set class variables, call a class method, etc., and all of that will be available in all tests.
Example:
require "minitest/autorun"
class MySpec < MiniTest::Spec
class MyClass
end
def self.prepare
puts "once"
##prepared = "prepared"
##count = 0
end
prepare
before do
puts "before each test"
#local_count = (##count += 1)
end
describe "whatever" do
it "first" do
p MyClass
p ##prepared
p #local_count
end
it "second" do
p MyClass
p ##prepared
p #local_count
end
end
end
Here's the output, along with my comments in braces explaining what each line of the output proves:
once [this code, a class method, runs once before all tests]
Run options: --seed 29618 [now the tests are about to run]
# Running tests:
before each test [the before block runs before each test]
MySpec::MyClass [the class we created earlier is visible in each test]
"prepared" [the class variable we set earlier is visible in each test]
1 [the instance variable from the before block is visible in each test]
before each test [the before block runs before each test]
MySpec::MyClass [the class we created earlier is visible in each test]
"prepared" [the class variable we set earlier is visible in each test]
2 [the instance variable from the before block is visible each test]
(Note that I do not mean this output to imply any guarantee about the order in which tests will run.)
Another approach is to use the existing before but wrap code to run only once in a class variable flag. Example:
class MySpec < MiniTest::Spec
##flag = nil
before do
unless ##flag
# do stuff here that is to be done only once
##flag = true
end
# do stuff here that is to be done every time
end
# ... tests go here
end
One simple way to do this is to write a guarded class method, and then call that in a begin.
A Minitest::Spec example:
describe "my stuff" do
def self.run_setup_code
if #before_flag.nil?
puts "Running the setup code"
#before_flag = true
end
end
before do
self.class.run_setup_code
end
it "will only run the setup code once" do
assert_equal 1, 1
end
it "really only ran it once" do
assert_equal 1,1
end
end
...to get
Run options: --seed 11380
# Running:
Running the setup code
..
Finished in 0.001334s, 1499.2504 runs/s, 1499.2504 assertions/s.
2 runs, 2 assertions, 0 failures, 0 errors, 0 skips
You can just place the code outside of the class.
This is what I do to have a banner.
require 'selenium-webdriver'
require 'minitest/test'
require 'minitest/autorun'
class InstanceTest < Minitest::Test
def setup
url = ARGV.first
#url = self.validate_instance(url)
#driver = Selenium::WebDriver.for :firefox
end
Nice thing about minitest is its flexibility. I've been using a custom MiniTest Runner with a +before_suite+ callback. Something like in this example - Ruby Minitest: Suite- or Class- level setup?
And then tell minitest to use the custom runner
MiniTest::Unit.runner = MiniTestSuite::Unit.new
You can also add an after test callback by updating your test_helper.rb (or spec_helper.rb) like this
# test_helper.rb
class MyTest < Minitest::Unit
after_tests do
# ... after test code
end
end

Ruby Watir can't find the assert method outside of the running class?

I have a class that I want to use in many test cases:
require 'rubygems'
require 'test/unit'
require 'watir'
class Tests < Test::Unit::TestCase
def self.Run(browser)
# make sure Summary of Changes exists
assert( browser.table(:class, "summary_table_class").exists? )
# make sure Snapshot of Change Areas exists
assert( browser.image(:xpath, "//div[#id='report_chart_div']/img").exists? )
# make sure Integrated Changes table exists
assert( browser.table(:id, 'change_table_html').exists? )
end
end
However, when run in one of my test cases:
require 'rubygems'
require 'test/unit'
require 'watir'
require 'configuration'
require 'Tests'
class TwoSCMCrossBranch < Test::Unit::TestCase
def test_two_scm_cross_branch
test_site = Constants.whatsInUrl
puts " Step 1: go to the test site: " + test_site
ie = Watir::IE.start(test_site)
Tests.Run(ie)
end
end
I get the error:
NoMethodError: undefined method `assert' for Tests:Class
C:/p4/dev/webToolKit/test/webapps/WhatsIn/ruby-tests/Tests.rb:8:in `Run'
What's missing? Thanks!
assert() is an instance method on TestCase so would only be available to instances of Tests. You are calling it inside a class method so Ruby is looking for a class method in Tests which doesn't exist.
A better way to do this is to make Tests a module and the Run method an instance method:
module Tests
def Run(browser)
...
end
end
Then include the Tests module in your test class:
class TwoSCMCrossBranch < Test::Unit::TestCase
include Tests
def test_two_scm_cross_branch
test_site = Constants.whatsInUrl
puts " Step 1: go to the test site: " + test_site
ie = Watir::IE.start(test_site)
Run(ie)
end
end
which will make the Run method available to the test and Run() will find the assert() method in the test class.
It might be worth a try to remove the asserts all together, and just use .exists?.

Resources