test_xml 0.0.4 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +8 -0
  3. data/Gemfile.lock +31 -0
  4. data/README.rdoc +56 -73
  5. data/Rakefile +12 -12
  6. data/lib/test_xml.rb +0 -2
  7. data/lib/test_xml/matcher_methods.rb +29 -0
  8. data/lib/test_xml/mini_test.rb +6 -0
  9. data/lib/test_xml/nokogiri/node.rb +13 -8
  10. data/lib/test_xml/spec.rb +1 -4
  11. data/lib/test_xml/spec/matchers.rb +5 -4
  12. data/lib/test_xml/spec/matchers/{match_xml.rb → contain_xml.rb} +2 -7
  13. data/lib/test_xml/spec/matchers/{match_xml_structure.rb → contain_xml_structure.rb} +2 -5
  14. data/lib/test_xml/spec/matchers/{exactly_match_xml.rb → equal_xml.rb} +2 -7
  15. data/lib/test_xml/spec/matchers/{exactly_match_xml_structure.rb → equal_xml_structure.rb} +2 -4
  16. data/lib/test_xml/test_unit.rb +2 -0
  17. data/lib/test_xml/test_unit/assertions.rb +29 -32
  18. data/lib/test_xml/version.rb +1 -1
  19. data/spec/{lib/test_xml/spec/matchers/match_xml_spec.rb → matchers/contain_xml_spec.rb} +5 -5
  20. data/spec/{lib/test_xml/spec/matchers/match_xml_structure_spec.rb → matchers/contain_xml_structure_spec.rb} +4 -4
  21. data/spec/{lib/test_xml/spec/matchers/exactly_match_xml_spec.rb → matchers/equal_xml_spec.rb} +6 -4
  22. data/spec/{lib/test_xml/spec/matchers/exactly_match_xml_structure_spec.rb → matchers/equal_xml_structure_spec.rb} +4 -4
  23. data/spec/spec.opts +2 -0
  24. data/spec/spec_helper.rb +1 -4
  25. data/test/{test_xml/nokogiri → nokogiri}/test_node.rb +14 -7
  26. data/test/test_helper.rb +1 -4
  27. data/test/test_unit/test_assertions.rb +227 -0
  28. data/test_xml.gemspec +28 -0
  29. metadata +77 -42
  30. data/test/test_xml/test_unit/test_assertions.rb +0 -159
@@ -0,0 +1,2 @@
1
+ *.gem
2
+ *.swp
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'rspec', ">= 2.2"
7
+ gem 'rdoc'
8
+ end
@@ -0,0 +1,31 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ test_xml (0.0.4)
5
+ nokogiri (>= 1.3.2)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.1.2)
11
+ nokogiri (1.4.4)
12
+ rake (0.8.7)
13
+ rdoc (3.5.3)
14
+ rspec (2.5.0)
15
+ rspec-core (~> 2.5.0)
16
+ rspec-expectations (~> 2.5.0)
17
+ rspec-mocks (~> 2.5.0)
18
+ rspec-core (2.5.1)
19
+ rspec-expectations (2.5.0)
20
+ diff-lcs (~> 1.1.2)
21
+ rspec-mocks (2.5.0)
22
+
23
+ PLATFORMS
24
+ ruby
25
+
26
+ DEPENDENCIES
27
+ rake
28
+ rdoc
29
+ rspec (>= 2.2)
30
+ rspec-core (~> 2.2)
31
+ test_xml!
@@ -1,24 +1,46 @@
1
1
  = TestXml
2
2
 
3
+
3
4
  == DESCRIPTION:
4
5
 
5
- TestXml is a small extension for RSpec and TestUnit for XML/HTML testing. I have found it very useful for API testing with our Cucumber tests.
6
+ TestXml is a small extension for testing XML/HTML. Extending RSpec and TestUnit it makes asserting and comparing XML snippets easy, and is especially helpful for testing RESTful web services and their XML representations.
7
+
6
8
 
7
9
  == FEATURES:
8
10
 
9
- * test XML with: RSpec, Test::Unit, Cucumber
10
- * test XML structure (partially or fully matched)
11
- * test the element values within XML structure
11
+ * runs with RSpec2, Test::Unit, MiniTest and Cucumber
12
+ * Ruby 1.8 and 1.9
13
+ * test XML structure and content
14
+
15
+
16
+ == INSTALL
17
+
18
+ gem install test_xml
19
+
12
20
 
13
21
  == EXAMPLES:
14
22
 
15
- === Cucumber feature
23
+ === Test::Unit and MiniTest
24
+
25
+ def test_item_representation
26
+ assert_xml_equal "<item><id>1</id></item>", @item.to_xml
27
+ end
28
+
29
+ === RSpec
30
+
31
+ it "should contain the id" do
32
+ @item.to_xml.should equal_xml(<<-XML)
33
+ <item>
34
+ <id>1</id>
35
+ </item>
36
+ XML
37
+ end
38
+
39
+ === Cucumber
16
40
 
17
41
  Scenario:
18
- Given data
19
- When I post the data
20
- The I receive successful response
21
- And response matches the following xml
42
+ When I post some data
43
+ Then the response should match the following xml
22
44
  """
23
45
  <transaction>
24
46
  <status>success</status>
@@ -27,97 +49,58 @@ TestXml is a small extension for RSpec and TestUnit for XML/HTML testing. I have
27
49
  </transaction>
28
50
  """
29
51
 
30
- The scenario will check:
31
-
32
- * 'status' element and its value.
33
- * 'id' and 'order_id' elements are present in XML
34
-
35
52
  == USAGE:
36
53
 
37
54
  === RSpec
38
55
 
39
- in spec_helper.rb
56
+ In your spec_helper.rb
40
57
 
41
- require 'test_xml'
42
58
  require 'test_xml/spec'
43
59
 
44
- in spec file:
45
-
46
- it "should match_xml" do
47
- xml = <<-XML
48
- <root>
49
- <one>1</one>
50
- <two>2</two>
51
- </root>
52
- XML
53
-
54
- xml.should match_xml(<<-XML)
55
- <root>
56
- <one>1</one>
57
- <two>2</two>
58
- </root>
59
- XML
60
- end
61
-
62
- === Implemented matchers
60
+ And in the actual spec, use these matchers:
63
61
 
64
- * match_xml
65
- * exactly_match_xml
66
- * match_xml_structure
67
- * exactly_match_xml_structure
62
+ * equal_xml
63
+ * contain_xml
64
+ * equal_xml_structure
65
+ * contain_xml_structure
68
66
 
69
- === With Test::Unit
67
+ === Test::Unit
70
68
 
71
- in test_helper.rb
69
+ In the test_helper.rb
72
70
 
73
- require 'test_xml'
74
71
  require 'test_xml/test_unit'
75
72
 
76
- in test file:
73
+ In your test file, use these matchers:
77
74
 
78
- def test_that_xml_matches
79
- xml = <<-XML
80
- <root>
81
- <one>1</one>
82
- </root>
83
- XML
75
+ * assert_xml_equal
76
+ * assert_xml_contain
77
+ * assert_xml_structure_equal
78
+ * assert_xml_structure_contain
84
79
 
85
- assert_match_xml(xml) do
86
- <<-XML
87
- <root>
88
- <one>1</one>
89
- </root>
90
- XML
91
- end
92
- end
80
+ Negative assertions are available as <tt>assert_not_*</tt>.
81
+
82
+ === MiniTest
93
83
 
94
- === Implemented assertions
84
+ In the test_helper.rb
95
85
 
96
- * assert_match_xml
97
- * assert_exactly_match_xml
98
- * assert_match_xml_structure
99
- * assert_exactly_match_xml_structure
86
+ require 'test_xml/mini_test'
100
87
 
101
- with assert_not_*
88
+ Check the Test::Unit section for available assertions.
102
89
 
103
- === With Cucumber
90
+ === Cucumber
104
91
 
105
- Add to features/env.rb
92
+ In the features/env.rb
106
93
 
107
94
  require 'test_xml'
108
95
  require 'test_xml/spec'
109
96
  World(TestXml::Spec)
110
97
 
111
- And you can add the following step:
112
-
113
- Then /^response matches the following xml$/ do |string|
98
+ In your steps file e.g. features/step_definitions/xml_steps.rb add this step:
99
+
100
+ Then /^the response should match the following xml$/ do |string|
114
101
  response.body.should match_xml(string)
115
102
  end
116
103
 
117
104
  == REQUIREMENTS
118
105
 
119
- test_xml depends on Nokogiri
120
-
121
- == INSTALL
122
-
123
- [sudo] gem install test_xml
106
+ * nokogiri
data/Rakefile CHANGED
@@ -1,22 +1,22 @@
1
- require 'rubygems'
2
- require 'rake'
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+ Bundler.setup
4
+
3
5
  require 'rake/testtask'
4
- require 'spec/rake/spectask'
6
+ require 'rspec/core/rake_task'
5
7
  require 'rdoc/task'
6
8
 
7
- task :default => ['test:units', :spec]
9
+ task :default => ['test', :spec]
8
10
 
9
- namespace :test do
10
- Rake::TestTask.new(:units) do |t|
11
- t.test_files = FileList['test/**/test_*.rb']
12
- t.libs << "test"
13
- t.verbose = true
14
- end
11
+ Rake::TestTask.new(:test) do |t|
12
+ t.test_files = FileList['test/**/test_*.rb']
13
+ t.libs << "test"
14
+ t.verbose = true
15
15
  end
16
16
 
17
17
 
18
- Spec::Rake::SpecTask.new do |t|
19
- t.libs << "spec"
18
+ RSpec::Core::RakeTask.new do |t|
19
+ #t.libs << "spec"
20
20
  t.verbose = true
21
21
  end
22
22
 
@@ -1,5 +1,3 @@
1
- require 'rubygems'
2
1
  require 'nokogiri'
3
-
4
2
  require 'test_xml/nokogiri/node'
5
3
  require 'test_xml/nokogiri'
@@ -0,0 +1,29 @@
1
+ module TestXml
2
+ # This module implements the actual matchers with their conditions.
3
+ module MatcherMethods
4
+ def self.xml_contain(subject, pattern)
5
+ actual, expected = parse_xml(subject, pattern)
6
+ actual.match?(expected, true)
7
+ end
8
+
9
+ def self.xml_equal(subject, pattern)
10
+ actual, expected = parse_xml(subject, pattern)
11
+ actual.match?(expected, true) && expected.match?(actual, true)
12
+ end
13
+
14
+ def self.xml_structure_contain(subject, pattern)
15
+ actual, expected = parse_xml(subject, pattern)
16
+ actual.match?(expected)
17
+ end
18
+
19
+ def self.xml_structure_equal(subject, pattern)
20
+ actual, expected = parse_xml(subject, pattern)
21
+ actual.match?(expected) && expected.match?(actual)
22
+ end
23
+
24
+ private
25
+ def self.parse_xml(subject, pattern)
26
+ [Nokogiri::XML.parse(subject), Nokogiri::XML.parse(pattern)]
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,6 @@
1
+ require "test_xml"
2
+ require 'test_xml/test_unit/assertions'
3
+
4
+ class MiniTest::Unit::TestCase
5
+ include TestXml::TestUnit::Assertions
6
+ end
@@ -2,23 +2,29 @@ module TestXml
2
2
  module NokogiriExt
3
3
  module Node
4
4
  def match?(element, compare_value = false)
5
- if compare_value && element.text_element?
6
- equal_text?(element)
5
+ if compare_value && element.leaf?
6
+ comparable_attributes == element.comparable_attributes and equal_text?(element)
7
7
  else
8
8
  contains_elements_of?(element) &&
9
9
  element.elements.all? {|el| matches_at_least_one?(el, compare_value) }
10
10
  end
11
11
  end
12
-
12
+
13
13
  def elements
14
14
  children.collect {|node| node if node.element? }.delete_if {|node| node.nil?}
15
15
  end
16
-
17
- def text_element?
18
- children.size == 1 && children.first.text?
16
+
17
+ # Attributes of the current node.
18
+ def comparable_attributes
19
+ attributes.collect {|k,a| [k.downcase, a.value]}.sort
20
+ end
21
+
22
+ # Check if node is either childless, self-closing, or has content text.
23
+ def leaf?
24
+ children.size == 0 or (children.size == 1 && children.first.text?)
19
25
  end
20
26
 
21
- private
27
+ private
22
28
  def equal_text?(element)
23
29
  content == element.content
24
30
  end
@@ -34,7 +40,6 @@ module TestXml
34
40
  def matches_at_least_one?(element, compare_value)
35
41
  search(element.name).find { |el| el.match?(element, compare_value) }
36
42
  end
37
-
38
43
  end
39
44
  end
40
45
  end
@@ -1,5 +1,2 @@
1
+ require 'test_xml'
1
2
  require 'test_xml/spec/matchers.rb'
2
-
3
- # class Spec::Example::ExampleGroup
4
- # include TestXml::Spec
5
- # end
@@ -1,4 +1,5 @@
1
- require 'test_xml/spec/matchers/match_xml'
2
- require 'test_xml/spec/matchers/match_xml_structure'
3
- require 'test_xml/spec/matchers/exactly_match_xml_structure'
4
- require 'test_xml/spec/matchers/exactly_match_xml'
1
+ require 'test_xml/matcher_methods'
2
+ require 'test_xml/spec/matchers/contain_xml'
3
+ require 'test_xml/spec/matchers/contain_xml_structure'
4
+ require 'test_xml/spec/matchers/equal_xml_structure'
5
+ require 'test_xml/spec/matchers/equal_xml'
@@ -1,11 +1,6 @@
1
- Spec::Matchers.define :match_xml do |expected|
1
+ RSpec::Matchers.define :contain_xml do |expected|
2
2
  match do |actual|
3
- subject = Nokogiri::XML::Document.parse(actual)
4
- pattern = Nokogiri::XML::Document.parse(expected)
5
-
6
- compare_values = true
7
-
8
- subject.match?(pattern, compare_values)
3
+ TestXml::MatcherMethods.xml_contain(actual, expected)
9
4
  end
10
5
 
11
6
  failure_message_for_should do |actual|
@@ -1,9 +1,6 @@
1
- Spec::Matchers.define :match_xml_structure do |expected|
1
+ RSpec::Matchers.define :contain_xml_structure do |expected|
2
2
  match do |actual|
3
- subject = Nokogiri::XML::Document.parse(actual)
4
- pattern = Nokogiri::XML::Document.parse(expected)
5
-
6
- subject.match?(pattern)
3
+ TestXml::MatcherMethods.xml_structure_contain(actual, expected)
7
4
  end
8
5
 
9
6
  failure_message_for_should do |actual|
@@ -1,11 +1,6 @@
1
- Spec::Matchers.define :exactly_match_xml do |expected|
1
+ RSpec::Matchers.define :equal_xml do |expected|
2
2
  match do |actual|
3
- subject = Nokogiri::XML::Document.parse(actual)
4
- pattern = Nokogiri::XML::Document.parse(expected)
5
-
6
- compare_values = true
7
-
8
- subject.match?(pattern, compare_values) && pattern.match?(subject, compare_values)
3
+ TestXml::MatcherMethods.xml_equal(actual, expected)
9
4
  end
10
5
 
11
6
  failure_message_for_should do |actual|
@@ -1,8 +1,6 @@
1
- Spec::Matchers.define :exactly_match_xml_structure do |expected|
1
+ RSpec::Matchers.define :equal_xml_structure do |expected|
2
2
  match do |actual|
3
- subject = Nokogiri::XML::Document.parse(actual)
4
- pattern = Nokogiri::XML::Document.parse(expected)
5
- subject.match?(pattern) && pattern.match?(subject)
3
+ TestXml::MatcherMethods.xml_structure_equal(actual, expected)
6
4
  end
7
5
 
8
6
  failure_message_for_should do |actual|
@@ -1,3 +1,5 @@
1
+ require "test/unit"
2
+ require "test_xml"
1
3
  require 'test_xml/test_unit/assertions'
2
4
 
3
5
  class Test::Unit::TestCase
@@ -1,53 +1,50 @@
1
+ require 'test_xml/matcher_methods'
2
+
1
3
  module TestXml
2
4
  module TestUnit
3
5
  module Assertions
4
- def self.assertions_for(name, options)
5
- define_method("assert_#{name}") do |subject, &block|
6
- pattern = block.call
7
-
8
- actual = Nokogiri::XML.parse(subject)
9
- expected = Nokogiri::XML.parse(pattern)
10
6
 
7
+ def self.assertions_for(name, options)
8
+ define_method("assert_#{name}") do |subject, pattern|
11
9
  full_message = options[:message_for_should].gsub(/\<pattern\>/, pattern).gsub(/\<subject\>/, subject)
12
10
 
13
- assert_block(full_message) do
14
- options[:matcher].call(actual, expected)
15
- end
11
+ correct_assert(MatcherMethods.send(name, subject, pattern), full_message)
16
12
  end
17
13
 
18
- define_method("assert_not_#{name}") do |subject, &block|
19
- pattern = block.call
20
-
21
- actual = Nokogiri::XML.parse(subject)
22
- expected = Nokogiri::XML.parse(pattern)
23
-
14
+ define_method("assert_not_#{name}") do |subject, pattern|
24
15
  full_message = options[:message_for_should_not].gsub(/\<pattern\>/, pattern).gsub(/\<subject\>/, subject)
25
16
 
26
- assert_block(full_message) do
27
- !options[:matcher].call(actual, expected)
28
- end
17
+ correct_assert(!MatcherMethods.send(name, subject, pattern), full_message)
29
18
  end
30
19
  end
20
+
21
+
22
+ assertions_for :xml_contain,
23
+ :message_for_should => "the xml:\n<subject>\nshould contain xml:\n<pattern>",
24
+ :message_for_should_not => "the xml:\n<subject>\nshould not contain xml:\n<pattern> but it does"
31
25
 
32
- assertions_for :match_xml,
33
- :message_for_should => "the xml:\n<subject>\nshould match xml:\n<pattern>",
34
- :message_for_should_not => "the xml:\n<subject>\nshould not match xml:\n<pattern> but it does",
35
- :matcher => Proc.new {|actual, expected| actual.match?(expected, true)}
36
-
37
- assertions_for :exactly_match_xml,
26
+ assertions_for :xml_equal,
38
27
  :message_for_should => "the xml:\n<subject>\nshould exactly match xml:\n<pattern>",
39
- :message_for_should_not => "the xml:\n<subject>\nshould not exactly match xml:\n<pattern> but it does",
40
- :matcher => Proc.new {|actual, expected| actual.match?(expected, true) && expected.match?(actual, true) }
28
+ :message_for_should_not => "the xml:\n<subject>\nshould not exactly match xml:\n<pattern> but it does"
41
29
 
42
- assertions_for :match_xml_structure,
30
+ assertions_for :xml_structure_contain,
43
31
  :message_for_should => "the xml:\n<subject>\nshould match xml structure:\n<pattern>",
44
- :message_for_should_not => "the xml:\n<subject>\nshould not match xml structure:\n<pattern> but it does",
45
- :matcher => Proc.new {|actual, expected| actual.match?(expected)}
32
+ :message_for_should_not => "the xml:\n<subject>\nshould not match xml structure:\n<pattern> but it does"
46
33
 
47
- assertions_for :exactly_match_xml_structure,
34
+ assertions_for :xml_structure_equal,
48
35
  :message_for_should => "the xml:\n<subject>\nshould exactly match xml structure:\n<pattern>",
49
- :message_for_should_not => "the xml:\n<subject>\nshould not exactly match xml structure:\n<pattern> but it does",
50
- :matcher => Proc.new {|actual, expected| actual.match?(expected) && expected.match?(actual) }
36
+ :message_for_should_not => "the xml:\n<subject>\nshould not exactly match xml structure:\n<pattern> but it does"
37
+
38
+ private
39
+ def correct_assert(boolean, message)
40
+ if RUBY_VERSION =~ /1.9.2/ or defined?(MiniTest)
41
+ assert(boolean, message)
42
+ else
43
+ assert_block(message) do
44
+ boolean
45
+ end
46
+ end
47
+ end
51
48
  end
52
49
  end
53
50
  end