Skip to content

Commit 03fecc4

Browse files
committed
✅ Generate parser tests from yaml fixtures
Currently defined test types: * `:parser_assert_equal`: compares parse result to the `expected` data. * `:parser_pending`: print out yaml which can be inserted into the appropriate yaml test fixture file. * `:assert_parse_failure`: asserts `ResponseParseError` is raised The two big motivations for this: 1) to simplify generation of test data from RFCs or other sources. 2) to simplify re-use of test data as benchmark data.
1 parent d3e473b commit 03fecc4

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# frozen_string_literal: true
2+
3+
require "net/imap"
4+
require "test/unit"
5+
require "yaml"
6+
7+
module NetIMAPTestHelpers
8+
module TestFixtureGenerators
9+
10+
attr_reader :fixtures
11+
12+
def load_fixture_data(*test_fixture_path)
13+
dir = self::TEST_FIXTURE_PATH
14+
YAML.unsafe_load_file File.join(dir, *test_fixture_path)
15+
end
16+
17+
def generate_tests_from(fixture_data: nil, fixture_file: nil)
18+
fixture_data ||= load_fixture_data fixture_file
19+
tests = fixture_data.fetch(:tests)
20+
21+
tests.each do |name, test|
22+
type = test.fetch(:test_type) {
23+
test.key?(:expected) ? :parser_assert_equal : :parser_pending
24+
}
25+
name = "test_#{name}" unless name.start_with? "test_"
26+
name = name.to_sym
27+
raise "#{name} is already defined" if instance_methods.include?(name)
28+
# warn "define_method :#{name} = #{type}..."
29+
30+
case type
31+
32+
when :parser_assert_equal
33+
test => response:, expected:;
34+
define_method name do
35+
with_debug do
36+
parser = Net::IMAP::ResponseParser.new
37+
actual = parser.parse response
38+
assert_equal expected, actual
39+
end
40+
end
41+
42+
when :parser_pending
43+
test => response:;
44+
define_method name do
45+
with_debug do
46+
parser = Net::IMAP::ResponseParser.new
47+
actual = parser.parse response
48+
puts YAML.dump name => {response:, expected: actual}
49+
pend "update tests with expected data..."
50+
end
51+
end
52+
53+
when :assert_parse_failure
54+
test => response:, message:;
55+
define_method name do
56+
err = assert_raise(Net::IMAP::ResponseParseError) do
57+
Net::IMAP::ResponseParser.new.parse response
58+
end
59+
assert_match(message, err.message)
60+
end
61+
62+
end
63+
end
64+
65+
end
66+
end
67+
68+
def with_debug(bool = true)
69+
Net::IMAP.debug, original = bool, Net::IMAP.debug
70+
yield
71+
ensure
72+
Net::IMAP.debug = original
73+
end
74+
75+
end

test/net/imap/test_imap_response_parser.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,14 @@
22

33
require "net/imap"
44
require "test/unit"
5+
require_relative "net_imap_test_helpers"
56

67
class IMAPResponseParserTest < Test::Unit::TestCase
8+
TEST_FIXTURE_PATH = File.join(__dir__, "fixtures/response_parser")
9+
10+
include NetIMAPTestHelpers
11+
extend NetIMAPTestHelpers::TestFixtureGenerators
12+
713
def setup
814
@do_not_reverse_lookup = Socket.do_not_reverse_lookup
915
Socket.do_not_reverse_lookup = true
@@ -13,6 +19,22 @@ def teardown
1319
Socket.do_not_reverse_lookup = @do_not_reverse_lookup
1420
end
1521

22+
############################################################################
23+
# Tests that do no more than parse an example response and assert the result
24+
# data has the correct values have been moved to yml test fixtures.
25+
#
26+
# TODO: add instructions for how to quickly add or update yaml tests
27+
############################################################################
28+
# Core IMAP specs, by RFC9051 section (w/ obsolete listed last):
29+
30+
############################################################################
31+
# IMAP extensions, by RFC:
32+
33+
############################################################################
34+
# More interesting tests about the behavior, either of the test or of the
35+
# response data, should still use normal tests, below
36+
############################################################################
37+
1638
def test_flag_list_many_same_flags
1739
parser = Net::IMAP::ResponseParser.new
1840
assert_nothing_raised do

0 commit comments

Comments
 (0)