You could have a very course test that goes something like this:
class ExamplesToCodeTest < Test::Unit::TestCase
def test_convert
# have some example markdown files in a fixtures directory
ExamplesToCode.convert("test/fixtures/*.markdown")
assert_equal expected_output_1, File.read("test/output/file_1.cs")
assert_equal expected_output_2, File.read("test/output/file_2.cs")
assert_equal expected_output_3, File.read("test/output/file_3.cs")
end
private
def expected_output_1
"... expected stuff here ..."
end
def expected_output_2
"... expected stuff here ..."
end
def expected_output_3
"... expected stuff here ..."
end
end
I suppose that would make a decent integration test, but that's not what I really like, I like to have my code in bite-size chunks
First I'd create a class that can handle parsing a markdown file, e.g.:
class MarkdownReaderTest < Test::Unit::TestCase
def test_read_code_sample_1
reader = MarkdownReader.new
code_sample = reader.read("fixtures/code_sample_1.markdown")
# or maybe something like this:
# code_sample = reader.parse(File.read("fixtures/code_sample_1.markdown"))
# if you want the reader to just be a parser...
assert_equal code_sample_1, code_sample
end
# ... repeat for other types of code samples ...
private
def code_sample_1
"text of code sample 1 here..."
end
end
Now all the code to read and parse markdown files is in the MarkdownReader class. Now if we don't want to have to actually write files you can get fancy and do some mocking with RR or Mocha or something (I'm using rr here):
class CodeSampleWriter < Test::Unit::TestCase
include RR::Adapters::TestUnit
def test_write_code_sample
# assuming CodeSampleWriter class is using the File.write()...
any_instance_of(File) do |f|
mock(f).write(code_sample_text) { true }
end
writer = CodeSampleWriter.new
writer.write(code_sample_text)
end
private
def code_sample_text
"... code sample text here ..."
end
end
Now assuming the ExamplesToCode class uses the MarkdownReader and CodeSampleWriter classes, you can again use mock objects with RR like so:
class ExamplesToCodeTest < Test::Unit::TestCase
include RR::Adapters::TestUnit
def test_convert
# mock the dir, so we don't have to have an actual dir with files...
mock(Dir).glob("*.markdown") { markdown_file_paths }
# mock the reader, so we don't actually read files...
any_instance_of(MarkdownReader) do |reader|
mock(reader).read("file1.markdown") { code_sample_1 }
mock(reader).read("file2.markdown") { code_sample_1 }
mock(reader).read("file3.markdown") { code_sample_1 }
end
# mock the writer, so we don't actually write files...
any_instance_of(CodeSampleWriter) do |writer|
mock(writer).write_code_sample(code_sample_1) { true }
mock(writer).write_code_sample(code_sample_2) { true }
mock(writer).write_code_sample(code_sample_3) { true }
end
# now that the mocks are mocked, it's go time!
ExamplesToCode.new.convert("*.markdown")
end
private
def markdown_file_paths
["file1.markdown", "file2.markdown", "file3.markdown"]
end
def code_sample_1; "... contents of file 1 ..."; end
def code_sample_2; "... contents of file 2 ..."; end
def code_sample_3; "... contents of file 3 ..."; end
end
Hopefully this gives you some ideas of how to approach testing in Ruby. Not be inflammatory, but for the most part, dependency injection is not something seen or used in the Ruby world -- it generally adds a lot of overhead. Mocking/Doubles are generally a much better option for testing.