Skip navigation.

Attractive Ruby tests that use multi-line strings

Attractive Ruby tests that use multi-line strings

Suppose you're testing some method whose input is a multi-line string. You could write something like this:

  def test_tags_can_be_deeply_nested    table = "<table>              <tr><td>                <table>                 <tr>                  <td>                    <table>                     <tr>                        <td>                             Way nested                        </td>                     </tr>                    </table>                  </td>                 </tr>                </table>              </td></tr>             </table>"    slices = TagSlices.new(table, "table")    # blah blah blah  end

That's fine - unless whitespace in the middle of the string is significant. The above method has no whitespace on the string's first line, but a whole lot on the others. What if I needed it all to be flush left? This is ugly:

  def test_tags_can_be_deeply_nested    table ="<table>  <tr><td>    <table>     <tr>      <td>        <table>          <tr>            <td>                 Way nested            </td>          </tr>        </table>      </td>     </tr>    </table>  </td></tr> </table>"    slices = TagSlices.new(table, "table")    # blah blah blah  end

I could argue that the ugliness makes it too hard to see the structure of the test and too hard to skim a file quickly and see what the tests are. That argument may even be true, but the real reason I don't like it is that it's ugly.

So I write such tests like this:

  def test_tags_can_be_deeply_nested    table = "<table>            . <tr><td>            .   <table>            .    <tr>            .     <td>            .       <table>            .         <tr>            .           <td>            .               Way nested            .           </td>            .         </tr>            .       </table>            .     </td>            .    </tr>            .   </table>            .                . </td></tr>            .</table>".unindent    slices = TagSlices.new(table, "table")    # blah blah blah  end

unindent removes the whitespace at the beginnings of lines, together with the discrete margin made of dots. Its code looks like this:

class String  def unindent    gsub(/^\s*\./m, '')  endend

I've fiddled around with unindent to a ridiculous degree, changing its name, how it works, how the margin is indicated. I think I've settled on this one.