stig 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 537946887fe8b354b53d3d239b4910b9bcf9064c
4
+ data.tar.gz: 9039195f3278ccdd1a8616899e4faf9851704234
5
+ SHA512:
6
+ metadata.gz: ec59581cf608be129b4b87f33d2bba035316c06a95c32f7f97569ffa145a8bf1e1bc1393e1091780f4a7e52fa7ae697cfb09610a0ee250d209b81e0829569790
7
+ data.tar.gz: 8f96bb1d14955d99a06f3b95a91c36170e65ec05236629962249425757d3a3c934cdfca9c46a84ec4d4533f95c23d85a86e3164bcd4cabb29410563c19fe72ce
@@ -0,0 +1,2 @@
1
+ vLg���>}�J������R��=�yP!t����:L���;����Ԣ��)ۻDPS`��/!����{�a[{��%�m1|䕿��:���kh���(y���G �$&kd���D
2
+ /<!f~�c�(��4���L��H/F�s�E#tGJw�(�^�9e��B��r�ox�k�!H'E᳇��Fuc�2I��PN�w⮙��h'8�$����@�o�EҤk�ॗ�a,*N�6�k��ڡ����thX_�����0�e��<
@@ -0,0 +1 @@
1
+ RKh':�R�R�t��w�����'|_ `t>f����|Y��Λk�Bz.��}��]9a�����`\�/�D{�D;�H��� *O�� ����dC�6=��s��b���f�ܯjtE�qh[n���n�>����\9`"{�AN�n�<����AlE2d>�K,��VK&2����D�.4�,�p��[�a�Ui��e9���B9��N�²�'g�Db�o��t���*%�?O�(CF��˴�{���;�Z+n/V�E�iA|�8N�
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2014 Jip van Reijsen
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,77 @@
1
+ # stig
2
+
3
+ Simple test input generation.
4
+
5
+ ## What is it
6
+
7
+ Stig is a small library for property based testing in Ruby. It runs a test
8
+ multiple times (100 by default) with randomly generated input. Stig is test
9
+ framework agnostic, so can be used with any test framework.
10
+
11
+ ## Usage
12
+
13
+ An example using [cutest][cutest]. `test` and `assert_raise` come from cutest.
14
+
15
+ ```ruby
16
+ require "stig"
17
+
18
+ test "doesn't parse random input" do
19
+ Stig.property(String) do |string|
20
+ assert_raise { Library.parse(string) }
21
+ end
22
+ end
23
+ ```
24
+
25
+ `Stig.property` takes one or more generators and a predicate block. A generator
26
+ is an object implementing `#call` or `#random`. A predicate block is a block
27
+ that returns `true` for passed tests and `false` for failed test.
28
+
29
+ **Note**: In the above example `String` is used as generator. Stig doesn't
30
+ monkey-patch any classes. Refinements are used instead.
31
+
32
+ Stig ships with a few built in generators, such as `Date`, `Integer` and
33
+ `String`. They can be found under the `Stig::Generators` namespace. It's easy to
34
+ write your own generators using `Stig.generator` and `Stig.generator_for`.
35
+
36
+ An example of creating a custom generator using `Stig.generator`.
37
+
38
+ ```ruby
39
+ Person = Struct.new(:name, :age)
40
+
41
+ person_generator = generator do
42
+ Person.new Generators::String.random, Generators::Integer.random(99)
43
+ end
44
+
45
+ person_generator.call
46
+ # => #<struct Person name="M#uVfd7\tx\x1Eri]\x1F\x7F", age=95>
47
+ ```
48
+
49
+ An example of creating a custom generator using `Stig.generator_for`.
50
+
51
+ ```ruby
52
+ Person = Struct.new(:name, :age) do
53
+ def self.random
54
+ new Generators::String.random, Generators::Integer.random(99)
55
+ end
56
+ end
57
+
58
+ person_generator = generator_for(Person)
59
+
60
+ person_generator.call
61
+ # => #<struct Person name="-\x069|\x0F\x03Llq", age=6>
62
+ ```
63
+
64
+ To configure the number of tests stig should run set the environment variable
65
+ `STIG_NUMBER_OF_RUNS` to the desired number of test runs.
66
+
67
+ [cutest]: https://github.com/djanowski/cutest
68
+
69
+ ## Installation
70
+
71
+ `gem install stig`
72
+
73
+ Stig requires Ruby 2.0.0 or higher.
74
+
75
+ ## License
76
+
77
+ See the LICENSE file.
@@ -0,0 +1,134 @@
1
+ require "stig/refinements"
2
+
3
+ using Stig::Refinements
4
+
5
+ module Stig
6
+ # Public: Number of tests that should be run.
7
+ NUMBER_OF_RUNS = (ENV["STIG_NUMBER_OF_RUNS"] || 100).to_i
8
+
9
+ # Public: Raised when a test failed.
10
+ class AssertionFailed < StandardError; end
11
+
12
+ module_function
13
+
14
+ # Public: Tests a property with randomly generated input. The input comes from
15
+ # Generators, which are passed as arguments. The property is described in the
16
+ # block. A test has failed when the block returns a falsy value (false or
17
+ # nil).
18
+ #
19
+ # types - An object implementing #call or #random.
20
+ # block - A block that describes the property.
21
+ #
22
+ # Examples
23
+ #
24
+ # property(String, String) do |a,b|
25
+ # assert (a + b).start_with?(a)
26
+ # end
27
+ #
28
+ # property(-> { rand(10) }) do |a|
29
+ # assert a.between?(0, 10)
30
+ # end
31
+ #
32
+ # Returns true.
33
+ # Raises ArgumentError when an invalid generator was supplied.
34
+ # Raises ArgumentError when no generators were supplied.
35
+ # Raises ArgumentError when a generator generates too few values.
36
+ # Raises ArgumentError when no block was supplied.
37
+ # Raises Stig::AssertionFailed when a test failed.
38
+ def property(*types, &block)
39
+ offenders = types.reject do |type|
40
+ type.respond_to?(:call) || type.respond_to?(:random)
41
+ end
42
+
43
+ unless offenders.empty?
44
+ msg = "no #call or #random implemented for #{offenders.join ", "}"
45
+ raise ArgumentError, msg
46
+ end
47
+
48
+ unless block_given?
49
+ raise ArgumentError, "a block is required"
50
+ end
51
+
52
+ if types.empty?
53
+ raise ArgumentError, "no generators given, consider a unit test"
54
+ end
55
+
56
+ methods = types.map do |type|
57
+ type.respond_to?(:call) ? :call : :random
58
+ end
59
+
60
+ types_and_method = types.zip(methods)
61
+
62
+ 1.upto(NUMBER_OF_RUNS) do |i|
63
+ input = types_and_method.map { |type, method| type.send(method) }
64
+
65
+ result = yield(*input)
66
+
67
+ unless result
68
+ parameters = block.parameters.map(&:last).first(input.size)
69
+ formatted = parameters.zip(input).map do |a,v|
70
+ "- #{a} => #{v.inspect} (#{v.class})"
71
+ end
72
+
73
+ message = "Failed after #{i} test(s) with input\n" \
74
+ "#{formatted.join "\n"}"
75
+
76
+ raise AssertionFailed, message
77
+ end
78
+ end
79
+
80
+ return true
81
+ rescue StopIteration
82
+ offender = types
83
+ .select { |type| type.respond_to?(:peek) }
84
+ .find { |gen| gen.peek && false rescue true }
85
+
86
+ raise ArgumentError, "#{offender} generates too few values"
87
+ end
88
+
89
+ # Public: Creates a generator from a block.
90
+ #
91
+ # args - Any arguments that should be passed to the block.
92
+ # block - A block returning a random value.
93
+ #
94
+ # Examples
95
+ #
96
+ # float_generator = Stig.generator do
97
+ # rand
98
+ # end
99
+ #
100
+ # number_generator = Stig.generator(1, 100) do |min, max
101
+ # rand(min..max)
102
+ # end
103
+ #
104
+ # Returns a Proc.
105
+ # Raises ArgumentError if no block was passed.
106
+ def generator(*args, &block)
107
+ unless block_given?
108
+ raise ArgumentError, "no block given"
109
+ end
110
+
111
+ args.empty? ? block : proc { yield(*args) }
112
+ end
113
+
114
+ # Public: Creates a generator from an object. The object should respond to
115
+ # #random.
116
+ #
117
+ # object - An object implementing #random.
118
+ # args - Any arguments that should be passed to object#random.
119
+ #
120
+ # Examples
121
+ #
122
+ # # Assuming Integer.random is implemented and takes two arguments.
123
+ # integer_generator = generator_for(Integer, 1, 10)
124
+ #
125
+ # Returns a Proc.
126
+ # Raises ArgumentError if `object` does not respond to #random.
127
+ def generator_for(object, *args)
128
+ unless object.respond_to?(:random)
129
+ raise ArgumentError, "no #random implemented for #{object}"
130
+ end
131
+
132
+ generator(*args, &object.method(:random))
133
+ end
134
+ end
@@ -0,0 +1,8 @@
1
+ require "stig/generators/array"
2
+ require "stig/generators/character"
3
+ require "stig/generators/date"
4
+ require "stig/generators/float"
5
+ require "stig/generators/integer"
6
+ require "stig/generators/string"
7
+ require "stig/generators/symbol"
8
+ require "stig/generators/time"
@@ -0,0 +1,31 @@
1
+ module Stig
2
+ module Generators
3
+ module Array
4
+ # Public: Generates an random Array. Elements are generated by a
5
+ # generator. Size is variable, use a Range with equal start and end for a
6
+ # fixed size.
7
+ #
8
+ # generator - An object implementing #call or #random.
9
+ # size - A maximum size Integer or Range (default: 1..10).
10
+ #
11
+ # Returns an Array.
12
+ # Raises ArgumentError when an invalid generator was supplied.
13
+ def self.random(generator, size = 1..10)
14
+ unless generator.respond_to?(:call) || generator.respond_to?(:random)
15
+ msg = "no #call or #random implemented for #{generator}"
16
+ raise ArgumentError, msg
17
+ end
18
+
19
+ method = generator.respond_to?(:call) ? :call : :random
20
+
21
+ array = []
22
+
23
+ rand(size).times do
24
+ array << generator.send(method)
25
+ end
26
+
27
+ array
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,22 @@
1
+ module Stig
2
+ module Generators
3
+ module Character
4
+ ASCII = 0.upto(127).map(&:chr)
5
+ PRINTABLE = 32.upto(126).map(&:chr)
6
+ DIGITS = 48.upto(57).map(&:chr)
7
+ UPPERCASE = 65.upto(90).map(&:chr)
8
+ LOWERCASE = 97.upto(122).map(&:chr)
9
+ ALPHABET = UPPERCASE + LOWERCASE
10
+
11
+ # Public: Generates a random character.
12
+ #
13
+ # set - An Array of one character Strings.
14
+ #
15
+ # Returns a 1 character String.
16
+ # Raises ArgumentError when `set` is empty.
17
+ def self.random(set = ASCII)
18
+ set = set.sample || raise(ArgumentError, "character set is empty")
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+ require "date"
2
+
3
+ module Stig
4
+ module Generators
5
+ module Date
6
+ extend self
7
+
8
+ DEFAULT_INTERVAL = ::Date.new..::Date.today
9
+
10
+ # Public: Generates a random Date.
11
+ #
12
+ # range - An interval Range (default: Date.new..Date.today).
13
+ #
14
+ # Returns a Date.
15
+ def random(range = DEFAULT_INTERVAL)
16
+ rand(range)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ module Stig
2
+ module Generators
3
+ module Float
4
+ extend self
5
+
6
+ # Public: Generates a random Float.
7
+ #
8
+ # max - A maximum Float or Range (default 0.0..1.0).
9
+ #
10
+ # Returns a Float.
11
+ def random(max = 0.0..1.0)
12
+ rand(max)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,33 @@
1
+ module Stig
2
+ module Generators
3
+ module Hash
4
+ extend self
5
+
6
+ # Public: Generates a random Hash. If no keys are passed, a Hash with a
7
+ # default proc is returned.
8
+ #
9
+ # generator - An object implementing #call or #random.
10
+ # keys - Objects to use as Hash keys.
11
+ #
12
+ # Returns a Hash.
13
+ # Raises ArgumentError when an invalid generator was supplied.
14
+ def random(generator, *keys)
15
+ unless generator.respond_to?(:call) || generator.respond_to?(:random)
16
+ msg = "no #call or #random implemented for #{generator}"
17
+ raise ArgumentError, msg
18
+ end
19
+
20
+ method = generator.respond_to?(:call) ? :call : :random
21
+
22
+ if keys.empty?
23
+ hash = ::Hash.new { |hash, key| hash[key] = generator.send(method) }
24
+ else
25
+ hash = {}
26
+ keys.each { |key| hash[key] = generator.send(method) }
27
+ end
28
+
29
+ hash
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,16 @@
1
+ module Stig
2
+ module Generators
3
+ module Integer
4
+ extend self
5
+
6
+ # Public: Generates a random Integer.
7
+ #
8
+ # max - A maximum Integer or Range (default: 100).
9
+ #
10
+ # Returns an Integer.
11
+ def random(max = 100)
12
+ rand(max)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,28 @@
1
+ require "stig/generators/character"
2
+
3
+ module Stig
4
+ module Generators
5
+ module String
6
+ extend self
7
+
8
+ # Public: Generates a random String. Characters are picked from a
9
+ # character set (`set`). Size is variable, use a Range with equal start
10
+ # and end for a fixed size.
11
+ #
12
+ # set - An Array of one character Strings (default: ASCII).
13
+ # size - A maximum length Integer or Range (default: 25).
14
+ #
15
+ # Returns a String.
16
+ def random(set = Character::ASCII, size = 25)
17
+ result = ""
18
+
19
+ rand(size).times do
20
+ char = set.sample || raise(ArgumentError, "character set is empty")
21
+ result << char
22
+ end
23
+
24
+ result
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,15 @@
1
+ module Stig
2
+ module Generators
3
+ module Symbol
4
+ extend self
5
+
6
+ # Public: Generates a random Symbol. See Stig::Generators::String for
7
+ # usage
8
+ #
9
+ # Returns a Symbol.
10
+ def random(*args)
11
+ Generators::String.random(*args).to_sym
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ module Stig
2
+ module Generators
3
+ module Time
4
+ extend self
5
+
6
+ DEFAULT_INTERVAL = ::Time.at(0)..::Time.now
7
+
8
+ # Public: Generates a random Time.
9
+ #
10
+ # interval - An interval Range (default: Time.at(0)..Time.now).
11
+ #
12
+ # Returns a Time.
13
+ def random(interval = DEFAULT_INTERVAL)
14
+ rand(interval)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,115 @@
1
+ require "stig/generators/date"
2
+ require "stig/generators/float"
3
+ require "stig/generators/integer"
4
+ require "stig/generators/string"
5
+ require "stig/generators/symbol"
6
+ require "stig/generators/time"
7
+
8
+ module Stig
9
+ # Public: Refinements for the core classes Array, Float, Integer and String.
10
+ module Refinements
11
+ # A note on refinements.
12
+ #
13
+ # There are a few issues with refinements:
14
+ #
15
+ # 1. Refined class methods are ignored. Calling them results in a
16
+ # NoMethodError.
17
+ # 2. #respond_to? ignores refined methods. It returns `false` for methods
18
+ # that have been refined.
19
+ # 3. #send ignores refined methods. It raises a NoMethodError when trying
20
+ # to invoke a refined method.
21
+ #
22
+ # Issues 2 and 3 aren't bugs, see: http://goo.gl/335ndw.
23
+ #
24
+ # Stig uses the following workarounds:
25
+ #
26
+ # 1. To refine class method, the singleton class is refined.
27
+ # 2. #respond_to? is refined. It checks for existing methods manually. The
28
+ # module Fix is included in the refinement.
29
+ # 3. #send is refined. Unfortunately, this cannot be done by including a
30
+ # module in the refinement. #send needs to be defined directly in the
31
+ # refinement or it will be ignored. It also requires any method it calls
32
+ # to be defined directly in the refinement.
33
+ #
34
+ # It's a pity.
35
+
36
+ # Internal: Fixes #respond_to? for refined classes.
37
+ module Fix
38
+ def respond_to?(method, *args)
39
+ method == :random ? true : super
40
+ end
41
+ end
42
+
43
+ refine Date.singleton_class do
44
+ include Fix
45
+
46
+ def random(*args, &block)
47
+ Generators::Date.random(*args, &block)
48
+ end
49
+
50
+ def send(method, *args, &block)
51
+ method == :random ? random(*args, &block) : super
52
+ end
53
+ end
54
+
55
+ refine Float.singleton_class do
56
+ include Fix
57
+
58
+ def random(*args, &block)
59
+ Generators::Float.random(*args, &block)
60
+ end
61
+
62
+ def send(method, *args, &block)
63
+ method == :random ? random(*args, &block) : super
64
+ end
65
+ end
66
+
67
+ refine Integer.singleton_class do
68
+ include Fix
69
+
70
+ def random(*args, &block)
71
+ Generators::Integer.random(*args, &block)
72
+ end
73
+
74
+ def send(method, *args, &block)
75
+ method == :random ? random(*args, &block) : super
76
+ end
77
+ end
78
+
79
+ refine String.singleton_class do
80
+ include Fix
81
+
82
+ def random(*args, &block)
83
+ Generators::String.random(*args, &block)
84
+ end
85
+
86
+ def send(method, *args, &block)
87
+ method == :random ? random(*args, &block) : super
88
+ end
89
+ end
90
+
91
+ refine Symbol.singleton_class do
92
+ include Fix
93
+
94
+ def random(*args, &block)
95
+ Generators::Symbol.random(*args, &block)
96
+ end
97
+
98
+ def send(method, *args, &block)
99
+ method == :random ? random(*args, &block) : super
100
+ end
101
+ end
102
+
103
+ refine Time.singleton_class do
104
+ include Fix
105
+
106
+ def random(*args, &block)
107
+ Generators::Time.random(*args, &block)
108
+ end
109
+
110
+ def send(method, *args, &block)
111
+ method == :random ? random(*args, &block) : super
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,3 @@
1
+ module Stig
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,18 @@
1
+ require_relative "lib/stig/version"
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "stig"
5
+ s.version = Stig::VERSION
6
+ s.summary = "simple test input generation"
7
+ s.description = "Stig is a small library for property based testing in Ruby."
8
+ s.author = "Jip van Reijsen"
9
+ s.email = "jipvanreijsen@gmail.com"
10
+ s.homepage = "https://github.com/britishtea/stig"
11
+ s.license = "MIT"
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.extra_rdoc_files = ["README.md"]
15
+ s.required_ruby_version = '>= 2.0'
16
+
17
+ s.add_development_dependency "cutest", "~> 1.2"
18
+ end
@@ -0,0 +1,7 @@
1
+ # Testing
2
+
3
+ [Cutest](cutest) is used for testing.
4
+
5
+ Running the tests is simple: `cutest test/*/*.rb`.
6
+
7
+ [cutest]: https://github.com/djanowski/cutest
@@ -0,0 +1,55 @@
1
+ require_relative "../test_helper"
2
+ require "stig"
3
+ require "stig/generators/array"
4
+
5
+ include Stig
6
+
7
+ setup { Stig::Generators::Array }
8
+
9
+ test "takes a generator" do |mod|
10
+ elements = generator { 1 }
11
+ generator = generator_for(mod, elements)
12
+
13
+ property(generator) do |array|
14
+ assert_equal array.uniq, [1]
15
+
16
+ true
17
+ end
18
+ end
19
+
20
+ test "doesn't take an invalid generator" do |mod|
21
+ assert_raise(ArgumentError) { mod.random("invalid") }
22
+ end
23
+
24
+ test "defaults to Arrays with length between 1 and 10" do |mod|
25
+ elements = generator { 1 }
26
+ generator = generator_for(mod, elements)
27
+
28
+ property(generator) do |array|
29
+ assert array.size.between?(1, 10)
30
+
31
+ true
32
+ end
33
+ end
34
+
35
+ test "takes a maximum size" do |mod|
36
+ elements = generator { 1 }
37
+ generator = generator_for(mod, elements, 5)
38
+
39
+ property(generator) do |array|
40
+ assert array.size.between?(0, 5)
41
+
42
+ true
43
+ end
44
+ end
45
+
46
+ test "takes a range" do |mod|
47
+ elements = generator { 1 }
48
+ generator = generator_for(mod, elements, 1..5)
49
+
50
+ property(generator) do |array|
51
+ assert array.size.between?(1, 5)
52
+
53
+ true
54
+ end
55
+ end
@@ -0,0 +1,41 @@
1
+ require_relative "../test_helper"
2
+ require "stig"
3
+ require "stig/generators/string"
4
+
5
+ include Stig
6
+
7
+ setup { Stig::Generators::Character }
8
+
9
+ test "defaults to all ASCII characters" do |mod|
10
+ property(mod) do |character|
11
+ assert_equal character.class, String
12
+
13
+ true
14
+ end
15
+
16
+ property(mod) do |character|
17
+ assert_equal character.size, 1
18
+
19
+ true
20
+ end
21
+
22
+ property(mod) do |character|
23
+ assert 0.upto(127).map(&:chr).include?(character)
24
+
25
+ true
26
+ end
27
+ end
28
+
29
+ test "takes a character set" do |mod|
30
+ generator = generator_for(mod, ["a"])
31
+
32
+ property(generator) do |character|
33
+ assert_equal character, "a"
34
+
35
+ true
36
+ end
37
+ end
38
+
39
+ test "doesn't take an empty character set" do |mod|
40
+ assert_raise(ArgumentError) { mod.random([]) }
41
+ end
@@ -0,0 +1,36 @@
1
+ require_relative "../test_helper"
2
+ require "stig"
3
+ require "stig/generators/date"
4
+
5
+ include Stig
6
+
7
+ setup { Stig::Generators::Date }
8
+
9
+ test "generates Dates" do |mod|
10
+ property(mod) do |date|
11
+ assert_equal date.class, Date
12
+
13
+ true
14
+ end
15
+ end
16
+
17
+ test "defaults between January 1, 4713 BCE and Date.today" do |mod|
18
+ range = Date.new..Date.today
19
+
20
+ property(mod) do |date|
21
+ assert range.cover?(date)
22
+
23
+ true
24
+ end
25
+ end
26
+
27
+ test "takes a Date Range" do |mod|
28
+ range = Date.new(0)..Date.new(5)
29
+ generator = generator_for(mod, range)
30
+
31
+ property(generator) do |date|
32
+ assert range.cover?(date)
33
+
34
+ true
35
+ end
36
+ end
@@ -0,0 +1,35 @@
1
+ require_relative "../test_helper"
2
+ require "stig"
3
+ require "stig/generators/float"
4
+
5
+ include Stig
6
+
7
+ setup { Stig::Generators::Float }
8
+
9
+ test "takes a maximum value" do |mod|
10
+ generator = generator_for(mod, 10.0)
11
+
12
+ property(generator) do |integer|
13
+ assert integer.between?(0.0, 10.0)
14
+
15
+ true
16
+ end
17
+ end
18
+
19
+ test "takes a range" do |mod|
20
+ generator = generator_for(mod, 5.0..10.0)
21
+
22
+ property(generator) do |integer|
23
+ assert integer.between?(5.0, 10.0)
24
+
25
+ true
26
+ end
27
+ end
28
+
29
+ test "defaults to Floats between 0.0 and 1.0" do |mod|
30
+ property(mod) do |integer|
31
+ assert integer.between?(0.0, 1.0)
32
+
33
+ true
34
+ end
35
+ end
@@ -0,0 +1,48 @@
1
+ require_relative "../test_helper"
2
+ require "stig"
3
+
4
+ setup { Stig }
5
+
6
+ prepare { $test = nil }
7
+
8
+ test "without a block" do |stig|
9
+ assert_raise(ArgumentError) { stig.generator }
10
+ end
11
+
12
+ test "with a block" do |stig|
13
+ generator = stig.generator { 1 }
14
+
15
+ assert_equal generator.class, Proc
16
+ assert_equal generator.call, 1
17
+ end
18
+
19
+ test "with a block taking arguments" do |stig|
20
+ arguments = [:a, :b, :c]
21
+ generator = stig.generator(*arguments) { |*args| args }
22
+
23
+ assert_equal generator.call, arguments
24
+ end
25
+
26
+ test "with an object without a #random" do |stig|
27
+ assert_raise(ArgumentError) { stig.generator_for "no #random" }
28
+ end
29
+
30
+ test "with an object responding to #random" do |stig|
31
+ object = Object.new
32
+ object.define_singleton_method(:random) { 1 }
33
+
34
+ generator = stig.generator_for(object)
35
+
36
+ assert_equal generator.class, Proc
37
+ assert_equal generator.call, 1
38
+ end
39
+
40
+ test "with an object taking arguments" do |stig|
41
+ object = Object.new
42
+ object.define_singleton_method(:random) { |*args| args }
43
+
44
+ arguments = [:a, :b, :c]
45
+ generator = stig.generator_for(object, *arguments)
46
+
47
+ assert_equal generator.call, arguments
48
+ end
@@ -0,0 +1,35 @@
1
+ require_relative "../test_helper"
2
+ require "stig"
3
+ require "stig/generators/hash"
4
+
5
+ include Stig
6
+
7
+ setup { Stig::Generators::Hash }
8
+
9
+ test "takes a generator" do |mod|
10
+ keys = generator { rand }
11
+ values = generator { 1 }
12
+ generator = generator_for(mod, values)
13
+
14
+ property(generator, keys) do |hash, key|
15
+ assert_equal hash[key], 1
16
+
17
+ true
18
+ end
19
+ end
20
+
21
+ test "takes a generator and a list of keys" do |mod|
22
+ keys = [:a, :b, :c]
23
+ values = generator { 1 }
24
+ generator = generator_for(mod, values, *keys)
25
+
26
+ property(generator) do |hash|
27
+ assert_equal hash, :a => 1, :b => 1, :c => 1
28
+
29
+ true
30
+ end
31
+ end
32
+
33
+ test "doesn't take an invalid generator" do |mod|
34
+ assert_raise(ArgumentError) { mod.random(1) }
35
+ end
@@ -0,0 +1,35 @@
1
+ require_relative "../test_helper"
2
+ require "stig"
3
+ require "stig/generators/integer"
4
+
5
+ include Stig
6
+
7
+ setup { Stig::Generators::Integer }
8
+
9
+ test "takes a maximum value" do |mod|
10
+ generator = generator_for(mod, 10)
11
+
12
+ property(generator) do |integer|
13
+ assert integer.between?(0, 10)
14
+
15
+ true
16
+ end
17
+ end
18
+
19
+ test "takes a range" do |mod|
20
+ generator = generator_for(mod, 5..10)
21
+
22
+ property(generator) do |integer|
23
+ assert integer.between?(5, 10)
24
+
25
+ true
26
+ end
27
+ end
28
+
29
+ test "defaults to Integers between 0 and 100" do |mod|
30
+ property(mod) do |integer|
31
+ assert integer.between?(0, 100)
32
+
33
+ true
34
+ end
35
+ end
@@ -0,0 +1,101 @@
1
+ require_relative "../test_helper"
2
+ require "stig"
3
+
4
+ GENERATOR = proc { 1 }
5
+ VERBOSITY = $VERBOSE
6
+
7
+ setup { Stig }
8
+
9
+ prepare do
10
+ $VERBOSE = VERBOSITY
11
+ $test = 0
12
+ end
13
+
14
+ test "no generators" do |stig|
15
+ assert_raise(ArgumentError) do
16
+ stig.property { true }
17
+ end
18
+ end
19
+
20
+ test "invalid generators" do |stig|
21
+ assert_raise(ArgumentError) do
22
+ stig.property("invalid", GENERATOR) { true }
23
+ end
24
+
25
+ assert_raise(ArgumentError) do
26
+ stig.property([].each) { true }
27
+ end
28
+ end
29
+
30
+ test "an object implementing #call as generator" do |stig|
31
+ generator = proc { 1 }
32
+
33
+ stig.property(generator) do |i|
34
+ assert_equal i, 1
35
+
36
+ true
37
+ end
38
+ end
39
+
40
+ test "an object implemeting #random as generator" do |stig|
41
+ generator = Object.new
42
+ generator.define_singleton_method(:random) { 1 }
43
+
44
+ stig.property(generator) do |i|
45
+ assert_equal i, 1
46
+
47
+ true
48
+ end
49
+ end
50
+
51
+ test "multiple generators" do |stig|
52
+ stig.property(GENERATOR, GENERATOR, GENERATOR) do |i,j,k|
53
+ assert_equal i, 1
54
+ assert_equal j, 1
55
+ assert_equal k, 1
56
+
57
+ true
58
+ end
59
+ end
60
+
61
+ test "no property" do |stig|
62
+ assert_raise(ArgumentError) { stig.property(GENERATOR) }
63
+ end
64
+
65
+ test "raises when a test fails" do |stig|
66
+ assert_raise(Stig::AssertionFailed) do
67
+ stig.property(GENERATOR) { false }
68
+ end
69
+ end
70
+
71
+ test "return true when all tests pass" do |stig|
72
+ assert stig.property(GENERATOR) { |i| true }
73
+ end
74
+
75
+ test "default number of runs" do |stig|
76
+ stig.property(GENERATOR) { $test += 1 }
77
+
78
+ assert_equal $test, 100
79
+ end
80
+
81
+ test "configure number of runs with constant" do |stig|
82
+ $VERBOSE = nil
83
+ stig::NUMBER_OF_RUNS = 2
84
+ $VERBOSE = VERBOSITY
85
+
86
+ stig.property(GENERATOR) { $test += 1 }
87
+
88
+ assert_equal $test, 2
89
+ end
90
+
91
+ test "configure number of runs with environment variable" do |stig|
92
+ ENV["STIG_NUMBER_OF_RUNS"] = "2"
93
+
94
+ $VERBOSE = nil
95
+ load "stig.rb"
96
+ $VERBOSE = VERBOSITY
97
+
98
+ stig.property(GENERATOR) { $test += 1 }
99
+
100
+ assert_equal $test, 2
101
+ end
@@ -0,0 +1,11 @@
1
+ require_relative "../test_helper"
2
+ require "stig"
3
+
4
+ test "doesn't pollute the global namespace" do
5
+ [Date, Float, Integer, String, Symbol, Time].each do |klass|
6
+ assert_equal klass.respond_to?(:random), false
7
+
8
+ # We just want this not to blow up.
9
+ Stig.property(klass) { true }
10
+ end
11
+ end
@@ -0,0 +1,63 @@
1
+ require_relative "../test_helper"
2
+ require "stig"
3
+ require "stig/generators/string"
4
+
5
+ include Stig
6
+
7
+ setup { Stig::Generators::String }
8
+
9
+ test "defaults to all ASCII characters with maximum length 25" do |mod|
10
+ set = Stig::Generators::Character::ASCII
11
+
12
+ property(mod) do |string|
13
+ assert string.chars.all? { |char| set.include? char }
14
+
15
+ true
16
+ end
17
+
18
+ property(mod) do |string|
19
+ assert string.size.between?(0, 25)
20
+
21
+ true
22
+ end
23
+ end
24
+
25
+ test "takes character sets" do |mod|
26
+ generator = generator_for(mod, ["a"])
27
+
28
+ property(generator) do |string|
29
+ assert_equal string.class, String
30
+
31
+ true
32
+ end
33
+
34
+ property(generator) do |string|
35
+ assert [["a"], []].include?(string.chars.uniq)
36
+
37
+ true
38
+ end
39
+ end
40
+
41
+ test "doesn't take an empty character set" do |mod|
42
+ assert_raise(ArgumentError) { mod.random([]) }
43
+ end
44
+
45
+ test "takes a maximum length" do |mod|
46
+ generator = generator_for(mod, ["a"], 10)
47
+
48
+ property(generator) do |string|
49
+ assert string.size.between?(0, 10)
50
+
51
+ true
52
+ end
53
+ end
54
+
55
+ test "takes a range as length" do |mod|
56
+ generator = generator_for(mod, ["a"], 5..10)
57
+
58
+ property(generator) do |string|
59
+ assert string.size.between?(5, 10)
60
+
61
+ true
62
+ end
63
+ end
@@ -0,0 +1,63 @@
1
+ require_relative "../test_helper"
2
+ require "stig"
3
+ require "stig/generators/symbol"
4
+
5
+ include Stig
6
+
7
+ setup { Stig::Generators::Symbol }
8
+
9
+ test "defaults to all ASCII characters with maximum length 25" do |mod|
10
+ set = Stig::Generators::Character::ASCII
11
+
12
+ property(mod) do |symbol|
13
+ assert symbol.to_s.chars.all? { |char| set.include? char }
14
+
15
+ true
16
+ end
17
+
18
+ property(mod) do |symbol|
19
+ assert symbol.size.between?(0, 25)
20
+
21
+ true
22
+ end
23
+ end
24
+
25
+ test "takes character sets" do |mod|
26
+ generator = generator_for(mod, ["a"])
27
+
28
+ property(generator) do |symbol|
29
+ assert_equal symbol.class, Symbol
30
+
31
+ true
32
+ end
33
+
34
+ property(generator) do |symbol|
35
+ assert [["a"], []].include?(symbol.to_s.chars.uniq)
36
+
37
+ true
38
+ end
39
+ end
40
+
41
+ test "doesn't take an empty character set" do |mod|
42
+ assert_raise(ArgumentError) { mod.random([]) }
43
+ end
44
+
45
+ test "takes a maximum length" do |mod|
46
+ generator = generator_for(mod, ["a"], 10)
47
+
48
+ property(generator) do |symbol|
49
+ assert symbol.size.between?(0, 10)
50
+
51
+ true
52
+ end
53
+ end
54
+
55
+ test "takes a range as length" do |mod|
56
+ generator = generator_for(mod, ["a"], 5..10)
57
+
58
+ property(generator) do |symbol|
59
+ assert symbol.size.between?(5, 10)
60
+
61
+ true
62
+ end
63
+ end
@@ -0,0 +1,34 @@
1
+ require_relative "../test_helper"
2
+ require "stig"
3
+ require "stig/generators/time"
4
+
5
+ include Stig
6
+
7
+ setup { Stig::Generators::Time }
8
+
9
+ test "defaults to dates between the UNIX epoch and \"now\"" do |mod|
10
+ range = Time.at(0)..Time.now
11
+
12
+ property(mod) do |time|
13
+ assert_equal time.class, Time
14
+
15
+ true
16
+ end
17
+
18
+ property(mod) do |time|
19
+ assert range.cover?(time)
20
+
21
+ true
22
+ end
23
+ end
24
+
25
+ test "takes a Range" do |mod|
26
+ range = Time.at(200)..Time.at(300)
27
+ generator = generator_for(mod, range)
28
+
29
+ property(generator) do |time|
30
+ assert range.cover?(time)
31
+
32
+ true
33
+ end
34
+ end
@@ -0,0 +1 @@
1
+ $:.unshift File.expand_path('../../lib', __FILE__)
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stig
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jip van Reijsen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDhTCCAm2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMRYwFAYDVQQDDA1qaXB2
14
+ YW5yZWlqc2VuMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ
15
+ FgNjb20wHhcNMTQwODIwMTcxOTMyWhcNMTUwODIwMTcxOTMyWjBEMRYwFAYDVQQD
16
+ DA1qaXB2YW5yZWlqc2VuMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJ
17
+ k/IsZAEZFgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsHlOk
18
+ 1hmzWghMsGRqmVXfBIYeJ6qZFOU9pYL+Zv7PkjqkC8O720+oXwMcANuT2IzHTdy+
19
+ rTEH8ctLioYGN5FI+lJPKsTtl3+KNwJdIP9h4W8t5RtxMTaPU1mI/jk6wKz2o2qy
20
+ u12J0cLKb7IWH19DAj2ZjAxmxQqTZsGt6VbAky2foZjo/x112wMSixzOEukW+O6W
21
+ fqBVnSjfOClhT+plelqlR5i1rz5YT6IL82D538AOU6tzLddH6XyHD+SygKpYKcV9
22
+ QUOXJGhTcUyA9WtgkaffIVlB5l4Ny6sT+CdEbI8N8htMziBjNcZul6/6CI+n0IDs
23
+ cJ4EorwzD5YXUAQzAgMBAAGjgYEwfzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAd
24
+ BgNVHQ4EFgQUNWHVVURPyyrVLTYn664v3mAEXXQwIgYDVR0RBBswGYEXamlwdmFu
25
+ cmVpanNlbkBnbWFpbC5jb20wIgYDVR0SBBswGYEXamlwdmFucmVpanNlbkBnbWFp
26
+ bC5jb20wDQYJKoZIhvcNAQEFBQADggEBAEwhZPajKIKnMrZag4vojHM0KNiTFOFN
27
+ rKW875s0/ZQ0vZQ8XafR+9HPflRntkdGMoXG1Z48w1ocUGkeuqg8he4q3sjEPHXK
28
+ Jd3lAIrlZDIH5EBIUjzOWJz+vtH6LfPwl73sHJ8TZ/bxZnianWq4UMPIxQywfrba
29
+ vtLKKRzrUpWQP67o9e0yLrfIWUl8AkCpcqsHMfgAPwvgtv0e2Hqfo74uPZ/u5wll
30
+ WXFwPdOwdBBrxe80pFe980gybYXGDKG9qljoAy9n/Z09I0mLTqN+Qk3LyBfV9JpJ
31
+ GwazeZftMqpbXP5J5qZq3KDKKFABsUKmL68rdLwTA6BZBqPA2D063qs=
32
+ -----END CERTIFICATE-----
33
+ date: 2014-12-08 00:00:00.000000000 Z
34
+ dependencies:
35
+ - !ruby/object:Gem::Dependency
36
+ name: cutest
37
+ requirement: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '1.2'
42
+ type: :development
43
+ prerelease: false
44
+ version_requirements: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '1.2'
49
+ description: Stig is a small library for property based testing in Ruby.
50
+ email: jipvanreijsen@gmail.com
51
+ executables: []
52
+ extensions: []
53
+ extra_rdoc_files:
54
+ - README.md
55
+ files:
56
+ - LICENSE
57
+ - README.md
58
+ - lib/stig.rb
59
+ - lib/stig/generators.rb
60
+ - lib/stig/generators/array.rb
61
+ - lib/stig/generators/character.rb
62
+ - lib/stig/generators/date.rb
63
+ - lib/stig/generators/float.rb
64
+ - lib/stig/generators/hash.rb
65
+ - lib/stig/generators/integer.rb
66
+ - lib/stig/generators/string.rb
67
+ - lib/stig/generators/symbol.rb
68
+ - lib/stig/generators/time.rb
69
+ - lib/stig/refinements.rb
70
+ - lib/stig/version.rb
71
+ - stig.gemspec
72
+ - test/README.md
73
+ - test/stig/array_generator.rb
74
+ - test/stig/character_generator.rb
75
+ - test/stig/date_generator.rb
76
+ - test/stig/float_generator.rb
77
+ - test/stig/generator.rb
78
+ - test/stig/hash_generator.rb
79
+ - test/stig/integer_generator.rb
80
+ - test/stig/property.rb
81
+ - test/stig/refinements.rb
82
+ - test/stig/string_generator.rb
83
+ - test/stig/symbol_generator.rb
84
+ - test/stig/time_generator.rb
85
+ - test/test_helper.rb
86
+ homepage: https://github.com/britishtea/stig
87
+ licenses:
88
+ - MIT
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '2.0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.2.2
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: simple test input generation
110
+ test_files: []
@@ -0,0 +1,2 @@
1
+ }�$�y��ɱ����{��tc�]`DoW��u ) �3�%�ɐM*fw�|)�}�zQ���������_n����i
2
+ Ҙ䣑5��(G=[A��I7�6�9�;��#���l:hXJ�����2�g�H��Ə�F�����;�䈬i#��G��+�7.���Ї������� u���]�R(��MՊK�%�DnX��r�����+��f/zA��T��$�6���߽�t_d��6�0�i�Z�x��.�9�