assert_type 0.0.5 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ assert_type
2
+ ===========
3
+
4
+ Provides a simple method to make assertions about the type of a value,
5
+ including nested types.
6
+
7
+ ## Installation
8
+
9
+ gem install assert_type
10
+
11
+ ## Example
12
+
13
+ ### Set-up
14
+
15
+ #### In development
16
+
17
+ Include the AssertType::AssertMethods module in Object,
18
+ which will make the assert_type method available anywhere.
19
+
20
+ It doesn't need to live in Object if you're not comfortable having it there.
21
+
22
+ ```ruby
23
+ require 'assert_type'
24
+ class Object
25
+ include AssertType::AssertMethods
26
+ end
27
+ ```
28
+
29
+ #### In production
30
+
31
+ Include the AssertType::NoOpMethods module instead of AssertType::AssertMethods
32
+ to include an assert_type method with the same signature that does nothing.
33
+
34
+ ```ruby
35
+ require 'assert_type'
36
+ class Object
37
+ include AssertType::NoOpMethods
38
+ end
39
+ ```
40
+
41
+ ### Making assertions
42
+
43
+ The first argument is the type string. It's based on YARD types. The entire YARD type syntax is not supported.
44
+
45
+ ```ruby
46
+ assert_type "Array", [] # wont raise
47
+ assert_type "Array", {} # will raise AssertType::AssertionError
48
+
49
+ assert_type "Array<Fixnum>", [1,2,3] # wont raise
50
+ assert_type "Array<Fixnum>", [] # wont raise
51
+ assert_type "Array<Fixnum>", [1.1,2.2,3.3] # will raise AssertType::AssertionError
52
+ assert_type "Array<Fixnum>", nil # will raise AssertType::AssertionError
53
+
54
+ assert_type "Array<Fixnum>, nil", [1,2,3] # wont raise
55
+ assert_type "Array<Fixnum>, nil", nil # wont raise
56
+
57
+ assert_type "String, Symbol", "three" # wont raise
58
+ assert_type "String, Symbol", :three # wont raise
59
+ assert_type "String, Symbol", 3 # will raise AssertType::AssertionError
60
+
61
+ assert_type "Array<String, Symbol>", ["three"] # wont raise
62
+ assert_type "Array<String, Symbol>", [:three] # wont raise
63
+ assert_type "Array<String, Symbol>", [] # wont raise
64
+ assert_type "Array<String, Symbol>", [3] # will raise AssertType::AssertionError
65
+
66
+ assert_type "Array<Set<Numeric>>", [Set.new([1,2])] # wont raise
67
+ assert_type "Array<Set<Numeric>>", [Set.new] # wont raise
68
+ assert_type "Array<Set<Numeric>>", [] # wont raise
69
+ assert_type "Array<Set<Numeric>>", [Set.new(["1","2"])] # will raise AssertType::AssertionError
70
+ assert_type "Array<Set<Numeric>>", [[1,2]] # will raise AssertType::AssertionError
71
+ assert_type "Array<Set<Numeric>>", [3] # will raise AssertType::AssertionError
72
+ ```
data/lib/assert_type.rb CHANGED
@@ -9,29 +9,13 @@ require "assert_type/type_validator"
9
9
  module AssertType
10
10
 
11
11
  module AssertMethods
12
- def at_assert truth
13
- unless truth
14
- raise AssertionError, "Expected truthy but was #{truth.inspect}"
15
- end
16
- end
17
-
18
- def at_assert_equal expected, actual
19
- unless expected == actual
20
- raise AssertionError.new expected, actual
21
- end
22
- end
23
12
 
24
- def at_assert_type expected_type, value
25
- if expected_type.is_a? Class
26
- unless expected_type === value
27
- raise TypeAssertionError.new expected_type.to_s, value
28
- end
29
- elsif expected_type.is_a? Array
30
- unless expected_type.any? {|t| t === value}
31
- types = expected_type.join(' or ')
32
- raise TypeAssertionError.new types, value
33
- end
34
- elsif expected_type.is_a? String
13
+ # @param expected_type [String] type string like "Array<Fixnum>"
14
+ # @param value [Object] value to check against type string
15
+ # @return [void]
16
+ # @raise [AssertType::AssertionError, AssertType::ParseError, AssertType::CallError]
17
+ def assert_type expected_type, value
18
+ if expected_type.is_a? String
35
19
  if node = AssertType::TypeStringParser.parse(expected_type)
36
20
  unless AssertType::TypeValidator.valid?(node, value)
37
21
  raise TypeAssertionError.new expected_type, value
@@ -43,17 +27,14 @@ module AssertType
43
27
  raise CallError.new
44
28
  end
45
29
  end
30
+
46
31
  end
47
32
 
48
33
  module NoOpMethods
49
- def at_assert *args
50
- end
51
34
 
52
- def at_assert_equal *args
35
+ def assert_type *args
53
36
  end
54
37
 
55
- def at_assert_type *args
56
- end
57
38
  end
58
39
 
59
40
  end
@@ -1,5 +1,7 @@
1
1
  require File.expand_path('./type_string_tokeniser.rb', File.dirname(__FILE__))
2
2
  require File.expand_path('./type_node.rb', File.dirname(__FILE__))
3
+ require File.expand_path('./parse_error.rb', File.dirname(__FILE__))
4
+
3
5
 
4
6
  module AssertType
5
7
  class TypeStringParser
@@ -14,6 +16,7 @@ module AssertType
14
16
  end
15
17
 
16
18
  def parse
19
+ quick_check_tokens
17
20
  root = TypeNode.root
18
21
  previous_word = root
19
22
  current_words = [root]
@@ -36,5 +39,33 @@ module AssertType
36
39
  @tokens ||= TypeStringTokeniser.tokenise @type_string
37
40
  end
38
41
 
42
+ def quick_check_tokens
43
+ unless check_angle_brackets_matched && check_angle_brackets_enclose_type
44
+ raise ParseError.new
45
+ end
46
+ end
47
+
48
+ def check_angle_brackets_matched
49
+ open_angle_brackets = 0
50
+ tokens.each do |token|
51
+ if token.name == :open_angle
52
+ open_angle_brackets += 1
53
+ elsif token.name == :close_angle
54
+ open_angle_brackets -= 1
55
+ end
56
+ return false if open_angle_brackets < 0
57
+ end
58
+ open_angle_brackets == 0
59
+ end
60
+
61
+ def check_angle_brackets_enclose_type
62
+ previous_name = nil
63
+ tokens.each do |token|
64
+ return false if previous_name == :open_angle && token.name != :word
65
+ previous_name = token.name
66
+ end
67
+ true
68
+ end
69
+
39
70
  end
40
71
  end
@@ -1,3 +1,5 @@
1
+ require File.expand_path('./parse_error.rb', File.dirname(__FILE__))
2
+
1
3
  module AssertType
2
4
  class TypeStringTokeniser
3
5
 
@@ -15,6 +17,7 @@ module AssertType
15
17
  while (t = next_token) do
16
18
  tokens << t
17
19
  end
20
+ raise ParseError.new unless @type_string.strip == ""
18
21
  tokens
19
22
  end
20
23
 
@@ -1,3 +1,3 @@
1
1
  module AssertType
2
- VERSION = "0.0.5"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -4,32 +4,54 @@ include AssertType::AssertMethods
4
4
 
5
5
  describe AssertType do
6
6
 
7
- it "quick and nasty tests" do
8
-
9
- at_assert_type Array, []
10
- at_assert_type "Array", []
11
- at_assert_type "Array", [1,2,3]
12
- at_assert_type "Array<Fixnum>", [1,2,3]
13
- at_assert_type "Array<Fixnum>", []
14
- expect { at_assert_type "Array<Fixnum>", ["one", "two", "three"] }.to raise_error(AssertType::AssertionError) { |error|
15
- error.message.should include %{expected Array<Fixnum> but was}
16
- }
17
- at_assert_type [Fixnum, String], 1
18
- at_assert_type [Fixnum, String], "1"
19
- expect { at_assert_type [Fixnum, String], 1.1 }.to raise_error(AssertType::AssertionError) { |error|
20
- error.message.should include %{expected Fixnum or String but was 1.1}
21
- }
22
- at_assert_type "Array<Fixnum>, nil", [1,2,3]
23
- at_assert_type "Array<Fixnum>, nil", []
24
- at_assert_type "Array<Fixnum>, nil", nil
25
- at_assert_type "String, Symbol", "hello"
26
- expect { at_assert_type "Array<Fixnum>, nil", false }.to raise_error(AssertType::AssertionError)
27
- expect { at_assert_type "Array<Fixnum>, nil", [nil] }.to raise_error(AssertType::AssertionError)
28
-
29
- at_assert_type "String, Symbol", "hello"
30
- at_assert_type "String, Symbol", :Symbol
31
- expect { at_assert_type "String, Symbol", 42 }.to raise_error(AssertType::AssertionError)
7
+ def self.example_valid expected_type, value
8
+ it "should not raise when asserting #{value.inspect} is a #{expected_type}" do
9
+ assert_type expected_type, value
10
+ end
11
+ end
12
+
13
+ def self.example_invalid expected_type, value
14
+ it "should raise assertion error when asserting #{value.inspect} is a #{expected_type}" do
15
+ expect { assert_type expected_type, value }.to raise_error(AssertType::AssertionError)
16
+ end
17
+ end
32
18
 
19
+ def self.example_call_error expected_type, value
20
+ it "should raise call error when asserting #{value.inspect} is a #{expected_type}" do
21
+ expect { assert_type expected_type, value }.to raise_error(AssertType::CallError)
22
+ end
33
23
  end
34
24
 
25
+ def self.example_parse_error expected_type, value
26
+ it "should raise parse error when asserting #{value.inspect} is a #{expected_type}" do
27
+ expect { assert_type expected_type, value }.to raise_error(AssertType::ParseError)
28
+ end
29
+ end
30
+
31
+ example_valid "Array", []
32
+ example_valid "Array", [1,2,3]
33
+
34
+ example_valid "Array<Fixnum>", [1,2,3]
35
+ example_valid "Array<Fixnum>", []
36
+ example_invalid "Array<Fixnum>", ["one", "two", "three"]
37
+
38
+ example_valid "Array<Fixnum>, nil", [1,2,3]
39
+ example_valid "Array<Fixnum>, nil", []
40
+ example_valid "Array<Fixnum>, nil", nil
41
+ example_invalid "Array<Fixnum>, nil", false
42
+ example_invalid "Array<Fixnum>, nil", [nil]
43
+
44
+ example_valid "String, Symbol", "hello"
45
+ example_valid "String, Symbol", :Symbol
46
+ example_invalid "String, Symbol", 42
47
+
48
+ example_call_error Array, []
49
+ example_call_error [Fixnum, String], 1
50
+ example_call_error [1,2,3], "Array<Fixnum>"
51
+
52
+ example_parse_error "Array<", []
53
+ example_parse_error "Array<>", []
54
+ example_parse_error "Array>", []
55
+ example_parse_error "A{B => C}", []
56
+
35
57
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: assert_type
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 5
10
- version: 0.0.5
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Joel Plane
@@ -30,6 +30,7 @@ extra_rdoc_files: []
30
30
  files:
31
31
  - .gitignore
32
32
  - Gemfile
33
+ - README.md
33
34
  - Rakefile
34
35
  - assert_type.gemspec
35
36
  - lib/assert_type.rb