In Ruby unit tests, how to assert that a string contains certain substring?

You could go with assert_match pattern, string, [message] which is true if string =~ pattern:

assert_match substring_to_verify, string_to_test

e.g.

assert_match /foo/, "foobar"

If you use this very often, why not write your own assertion?

require 'test/unit'

module Test::Unit::Assertions
  def assert_contains(expected_substring, string, *args)
    assert_match expected_substring, string, *args
  end
end

Alternatively, using the method described by @IvayloStrandjev (way easier to understand), you could define

require 'test/unit'

module Test::Unit::Assertions
  def assert_contains(expected_substring, string, *args)
    assert string.include?(expected_substring), *args
  end
end

The usage is exactly as you requested in your question, e.g.

class TestSimpleNumber < Test::Unit::TestCase
  def test_something
    assert_contains 'foo', 'foobar'
  end

  def test_something_fails
    assert_contains 'x', 'foobar', 'Does not contain x'
  end
end

Which will produce

Run options:

# Running tests:

.F

Finished tests in 0.000815s, 2453.9877 tests/s, 2453.9877 assertions/s.

  1) Failure:
test_something_fails(TestSimpleNumber) [assertion.rb:15]:
Does not contain x

2 tests, 2 assertions, 1 failures, 0 errors, 0 skips

Edit

As requested, with automated message:

module Test::Unit::Assertions
  def assert_contains(exp_substr, obj, msg=nil)
    msg = message(msg) { "Expected #{mu_pp obj} to contain #{mu_pp exp_substr}" }
    assert_respond_to obj, :include?
    assert obj.include?(exp_substr), msg
  end
end

adapted from the original assert_match source. This actually also works with Arrays!

assert_contains 3, [1,2,3]

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)