fakeit 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 46f41bf28d7b4e0775fe84baa2d134947daa0e1ab114c4ad92bc95f63dc678be
4
- data.tar.gz: ba497fcaf61e251e0316f7ac86223d84550f0c74d35db9319d3b152061de557b
3
+ metadata.gz: 9828311f1d6fb26ae16bf4bf4ec2fc5c52f5f88bfcdfc3df9ff4b9192671bf06
4
+ data.tar.gz: 6c739c443ae6506a9584ae8f41f37db3821ef7fc8533321bfdb762ef5d29a0ed
5
5
  SHA512:
6
- metadata.gz: b7579ea64592fb2106a6a4af5d747f49be9eca739410a0decc0efb97fab22813a59cf416b57f13cfbc3ae0487449e7e1a5350533c98581baaa078d2266e80689
7
- data.tar.gz: 42f1b09134e6f67cd933df04c00f9a154888830f500fd4d78a68bef780721d8f70f0409ee1a4d756640f5505783b2539d5856759f9096ff844fba5a023fdc843
6
+ metadata.gz: af522acb4552e1f45a6595a55aa1159ecf875813ac5547580fee0bd1a9962dfec73e58cc7f02cb53a0398b296537aca72f1cd733d2fbf0241994e9caf391e549
7
+ data.tar.gz: 9d0ddac0516f7019bb8459172f72570aa2d670d3aca019ac31deec62b165246438b1c0df3f1305a5ab6c9dd28344d195bf389a86b54150db00e3b5d14e90d058
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fakeit (0.2.1)
4
+ fakeit (0.3.0)
5
5
  faker (~> 1.9)
6
6
  openapi_parser (= 0.3.1)
7
7
  rack (~> 2.0)
@@ -31,7 +31,7 @@ GEM
31
31
  rack-test (1.1.0)
32
32
  rack (>= 1.0, < 3)
33
33
  rainbow (3.0.0)
34
- rake (12.3.2)
34
+ rake (12.3.3)
35
35
  rspec (3.8.0)
36
36
  rspec-core (~> 3.8.0)
37
37
  rspec-expectations (~> 3.8.0)
@@ -45,7 +45,7 @@ GEM
45
45
  diff-lcs (>= 1.2.0, < 2.0)
46
46
  rspec-support (~> 3.8.0)
47
47
  rspec-support (3.8.2)
48
- rubocop (0.72.0)
48
+ rubocop (0.74.0)
49
49
  jaro_winkler (~> 1.5.1)
50
50
  parallel (~> 1.10)
51
51
  parser (>= 2.6)
data/README.md CHANGED
@@ -9,6 +9,25 @@
9
9
 
10
10
  Create mock server from Openapi specification
11
11
 
12
+ ## Motivation
13
+
14
+ Openapi mock server is one of core components to support contract based development and testing. As part of our journal, several key requirements for such mock server have been identified:
15
+
16
+ * Control response generation in non intrusive manner. i.e. without modifying example in contract
17
+ * Randomly generated response to support property based testing
18
+ * Fulfill property reference in response generation to support development against contract. i.e. regarding the following response, guarantee the `selectedId` property is always a valid `id` in the items
19
+ ```json
20
+ {
21
+ "selectedId": 1,
22
+ "items": [
23
+ { "id": 1 },
24
+ { "id": 2 }
25
+ ]
26
+ }
27
+ ```
28
+
29
+ After tried several existing options, we cannot find a best solution to meet all the requirements. So we decide to __'Fakeit till you make it'__.
30
+
12
31
  ## Features
13
32
 
14
33
  * Randomly or statically generated response
@@ -34,14 +53,14 @@ Command line options:
34
53
 
35
54
  $ fakeit --help
36
55
  usage:
37
- --spec spec file uri (required)
38
- -p, --port custom port
39
- -q, --quiet mute request and response log
40
- --permissive log validation error as warning instead of denying request
41
- --use-example use example provided in spec if exists
42
-
43
- trial options:
44
- --static generate static response
56
+ --spec spec file uri (required)
57
+ -p, --port custom port
58
+ -q, --quiet mute request and response log
59
+ --permissive log validation error as warning instead of denying request
60
+ --use-example use example provided in spec if exists
61
+ --static generate static response
62
+ --static-types generate static value for specified types, e.g. --static-types integer,string
63
+ --static-properties generate static value for specified properties, e.g. --static-types id,uuid
45
64
 
46
65
  other options:
47
66
  -v, --version
data/bin/fakeit CHANGED
@@ -12,9 +12,9 @@ begin
12
12
  o.bool '-q', '--quiet', 'mute request and response log'
13
13
  o.bool '--permissive', 'log validation error as warning instead of denying request'
14
14
  o.bool '--use-example', 'use example provided in spec if exists'
15
- o.separator ''
16
- o.separator 'trial options:'
17
15
  o.bool '--static', 'generate static response'
16
+ o.array '--static-types', 'generate static value for specified types, e.g. --static-types integer,string'
17
+ o.array '--static-properties', 'generate static value for specified properties, e.g. --static-types id,uuid'
18
18
  o.separator ''
19
19
  o.separator 'other options:'
20
20
  o.on '-v', '--version' do
@@ -47,7 +47,9 @@ end
47
47
  options = Fakeit::App::Options.new(
48
48
  permissive: opts.permissive?,
49
49
  use_example: opts.use_example?,
50
- static: opts.static?
50
+ static: opts.static?,
51
+ static_types: opts[:static_types],
52
+ static_properties: opts[:static_properties]
51
53
  )
52
54
  app = Fakeit.build(opts[:spec], options)
53
55
 
@@ -21,11 +21,13 @@ The following Openapi properties are supported in random response generation
21
21
  | |minLength|Default: `0`|
22
22
  | |maxLength|Default: `minLength + 10`|
23
23
  |integer|enum| |
24
- | |minimum|Default: `-2^31`|
25
- | |maximum|Default: `2^31 - 1`|
24
+ | |minimum|Default: based on format|
25
+ | |maximum|Default: based on format|
26
26
  | |exclusiveMinimum| |
27
27
  | |exclusiveMaximum| |
28
28
  | |multipleOf| |
29
+ | |format=int32|`-2^31` ~ `2^31 - 1`|
30
+ | |format=int64|`-2^63` ~ `2^63 - 1`|
29
31
  |number|minimum|Default: `-2^31`|
30
32
  | |maximum|Default: `2^31 - 1`|
31
33
  | |multipleOf| |
@@ -24,6 +24,8 @@ Static value generation rule
24
24
  | |maximum|maximum|
25
25
  | |exclusiveMaximum|maximum - 1|
26
26
  | |multipleOf|maximum value meets multipleOf condition|
27
+ | |format=int32|`2^31 - 1`|
28
+ | |format=int64|`2^63 - 1`|
27
29
  |number|N/A|`2^31 - 1`|
28
30
  | |maximum|maximum rounded to 2 decimal places|
29
31
  | |multipleOf|maximum value meets multipleOf condition|
@@ -1,12 +1,18 @@
1
1
  module Fakeit
2
2
  module App
3
3
  class Options
4
- attr_reader :permissive, :use_example, :static
4
+ attr_reader :permissive, :use_example
5
5
 
6
- def initialize(permissive: false, use_example: false, static: false)
6
+ def initialize(permissive: false, use_example: false, static: false, static_types: [], static_properties: [])
7
7
  @permissive = permissive
8
8
  @use_example = use_example
9
9
  @static = static
10
+ @static_types = static_types
11
+ @static_properties = static_properties
12
+ end
13
+
14
+ def use_static?(type: nil, property: nil)
15
+ @static || @static_types.include?(type) || @static_properties.include?(property)
10
16
  end
11
17
  end
12
18
  end
@@ -3,7 +3,11 @@ module Fakeit
3
3
  module Example
4
4
  def array_example(options)
5
5
  example_options = add_depth(options)
6
- example_options[:static] ? static_array_example(example_options) : random_array_example(example_options)
6
+ if example_options[:use_static][type: 'array', property: example_options[:property]]
7
+ static_array_example(example_options)
8
+ else
9
+ random_array_example(example_options)
10
+ end
7
11
  end
8
12
 
9
13
  private
@@ -2,7 +2,7 @@ module Fakeit
2
2
  module Openapi
3
3
  module Example
4
4
  def boolean_example(example_options)
5
- example_options[:static] || Faker::Boolean.boolean
5
+ example_options[:use_static][type: 'boolean', property: example_options[:property]] || Faker::Boolean.boolean
6
6
  end
7
7
  end
8
8
  end
@@ -2,7 +2,11 @@ module Fakeit
2
2
  module Openapi
3
3
  module Example
4
4
  def integer_example(example_options)
5
- example_options[:static] ? static_integer_example : random_integer_example
5
+ if example_options[:use_static][type: 'integer', property: example_options[:property]]
6
+ static_integer_example
7
+ else
8
+ random_integer_example
9
+ end
6
10
  end
7
11
 
8
12
  private
@@ -5,7 +5,11 @@ module Fakeit
5
5
  MAX_NUM = 2**31 - 1
6
6
 
7
7
  def number_example(example_options)
8
- example_options[:static] ? static_number_example : random_number_example
8
+ if example_options[:use_static][type: 'number', property: example_options[:property]]
9
+ static_number_example
10
+ else
11
+ random_number_example
12
+ end
9
13
  end
10
14
 
11
15
  private
@@ -2,7 +2,9 @@ module Fakeit
2
2
  module Openapi
3
3
  module Example
4
4
  def object_example(example_options)
5
- properties.each_with_object({}) { |(name, schema), obj| obj[name] = schema.to_example(example_options) }
5
+ properties.each_with_object({}) do |(name, schema), obj|
6
+ obj[name] = schema.to_example(example_options.merge(property: name))
7
+ end
6
8
  end
7
9
  end
8
10
  end
@@ -23,22 +23,33 @@ module Fakeit
23
23
  }.freeze
24
24
 
25
25
  def string_example(example_options)
26
- example_options[:static] ? static_string_example : random_string_example
26
+ if example_options[:use_static][type: 'string', property: example_options[:property]]
27
+ static_string_example
28
+ else
29
+ random_string_example
30
+ end
27
31
  end
28
32
 
29
33
  private
30
34
 
31
35
  def static_string_example
32
- Faker::Config.random = Random.new(1) # Fix seed for faker
33
-
34
- if enum then enum.to_a.first
35
- elsif pattern then Faker::Base.regexify(pattern)
36
- elsif format then static_string_format
37
- elsif length_constraint then static_string_with_length
38
- else 'string'
36
+ fixed_faker do
37
+ if enum then enum.to_a.first
38
+ elsif pattern then Faker::Base.regexify(pattern)
39
+ elsif format then static_string_format
40
+ elsif length_constraint then static_string_with_length
41
+ else 'string'
42
+ end
39
43
  end
40
44
  end
41
45
 
46
+ def fixed_faker(&block)
47
+ Faker::Config.random = Random.new(1)
48
+ result = block.call
49
+ Faker::Config.random = nil
50
+ result
51
+ end
52
+
42
53
  def random_string_example
43
54
  if enum then enum.to_a.sample
44
55
  elsif pattern then Faker::Base.regexify(pattern)
@@ -14,9 +14,9 @@ module Fakeit
14
14
 
15
15
  def parse_method(src)
16
16
  case File.extname(src)
17
- when '.json' then
17
+ when '.json'
18
18
  JSON.method(:parse)
19
- when '.yml', '.yaml' then
19
+ when '.yml', '.yaml'
20
20
  YAML.method(:safe_load)
21
21
  else
22
22
  raise 'Invalid openapi specification file'
@@ -33,7 +33,7 @@ module Fakeit
33
33
  private
34
34
 
35
35
  def example_options
36
- { use_example: @app_options.use_example, static: @app_options.static, depth: 0 }
36
+ { use_example: @app_options.use_example, use_static: @app_options.method(:use_static?), depth: 0 }
37
37
  end
38
38
 
39
39
  def response_content
@@ -23,7 +23,11 @@ module Fakeit
23
23
  private
24
24
 
25
25
  def one_of_example(example_options)
26
- example_options[:static] ? one_of.first.to_example(example_options) : one_of.sample.to_example(example_options)
26
+ if example_options[:use_static][property: example_options[:property]]
27
+ one_of.first.to_example(example_options)
28
+ else
29
+ one_of.sample.to_example(example_options)
30
+ end
27
31
  end
28
32
 
29
33
  def all_of_example(example_options)
@@ -34,13 +38,23 @@ module Fakeit
34
38
  end
35
39
 
36
40
  def any_of_example(example_options)
37
- any_of
38
- .select { |option| option.type == 'object' }
39
- .then { |options| example_options[:static] ? options : options.sample(Faker::Number.between(1, any_of.size)) }
41
+ any_of_options(example_options)
40
42
  .map { |option| option.to_example(example_options) }
41
43
  .reduce(&:merge)
42
44
  end
43
45
 
46
+ def any_of_options(example_options)
47
+ any_of
48
+ .select { |option| option.type == 'object' }
49
+ .then do |options|
50
+ if example_options[:use_static][property: example_options[:property]]
51
+ options
52
+ else
53
+ options.sample(Faker::Number.between(1, any_of.size))
54
+ end
55
+ end
56
+ end
57
+
44
58
  def type_based_example(example_options)
45
59
  send("#{type}_example", example_options) if %w[string integer number boolean array object].include?(type)
46
60
  end
@@ -1,3 +1,3 @@
1
1
  module Fakeit
2
- VERSION = '0.2.1'.freeze
2
+ VERSION = '0.3.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fakeit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Feng
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-04 00:00:00.000000000 Z
11
+ date: 2019-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler