faked_csv 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +199 -0
- data/Rakefile +2 -0
- data/bin/faked_csv +3 -0
- data/example.csv.json +44 -0
- data/faked_csv.gemspec +31 -0
- data/features/faked_csv.feature +28 -0
- data/features/support/setup.rb +1 -0
- data/lib/faked_csv.rb +9 -0
- data/lib/faked_csv/cli.rb +65 -0
- data/lib/faked_csv/config.rb +111 -0
- data/lib/faked_csv/fakerer.rb +31 -0
- data/lib/faked_csv/generator.rb +170 -0
- data/lib/faked_csv/printer.rb +16 -0
- data/lib/faked_csv/version.rb +3 -0
- data/spec/config_spec.rb +26 -0
- data/spec/data/basic.csv.json +44 -0
- data/spec/data/inject.csv.json +10 -0
- data/spec/data/rotate.csv.json +36 -0
- data/spec/fakerer_spec.rb +28 -0
- data/spec/generator_spec.rb +140 -0
- data/spec/printer_spec.rb +15 -0
- data/spec/spec_helper.rb +4 -0
- metadata +206 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 56102a797c421e299e8ba038c686b6c513015b96
|
4
|
+
data.tar.gz: fba1e160834bd6f27d90896c258e9e30b2c588f8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 53d314f1d7eeffb899dfe8c17629aa8245c98e19e22e4455f02b1508d28953f1bd7ee35c8989dbe85740765172223ac8d955e97c40202f4787f54a04a271d0cf
|
7
|
+
data.tar.gz: 4704171816ab7dbd1751b72099ea51b8dccf92c543de2c679ca0cc6fc80edf9c47e0797aed507e78c4473f10c3f539bdac01d00cac9c849be9cc3146c7a65f83
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Jianan Lu
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,199 @@
|
|
1
|
+
# Faking CSV data made easy
|
2
|
+
|
3
|
+
faked_csv, using the awesome [Faker](https://github.com/stympy/faker) gem, helps you to generate CSV file with fake random data in your specified way. You may find it particularly useful in testing something out.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```
|
8
|
+
gem install faked_csv
|
9
|
+
```
|
10
|
+
|
11
|
+
Test your installation by running the following command in your terminal/console:
|
12
|
+
|
13
|
+
```
|
14
|
+
faked_csv --version
|
15
|
+
```
|
16
|
+
|
17
|
+
You can also install the gem using bundler.
|
18
|
+
|
19
|
+
The gem is developed and tested under Ruby 2.1.
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
For each faked CSV file, you first create a `<name>.csv.json` file that contains the configuration of how you want to generate the faked data, as hinted by the name, in `json` format.
|
24
|
+
|
25
|
+
## Example
|
26
|
+
|
27
|
+
A simple example `.csv.json` file looks like the following. Noted, JSON file doesn't support inline comment, so the below example is only for illustration. You can use the `example.csv.json` file in the root folder of the source code as a boilerplate. More details on the configuration file are in later section.
|
28
|
+
|
29
|
+
```
|
30
|
+
{
|
31
|
+
"rows": 200, <- how many rows in the generated CSV
|
32
|
+
"fields": [ <- a list of fields/columns in the generated CSV
|
33
|
+
{
|
34
|
+
"name": "ID", <- field/column name
|
35
|
+
"type": "rand:char", <- type/format of the field
|
36
|
+
"length": 5 <- 5 characters random word
|
37
|
+
},
|
38
|
+
{
|
39
|
+
"name": "First Name",
|
40
|
+
"type": "fixed", <- values will only come from the below list
|
41
|
+
"values": ["Peter", "Tom", "Jane", "Tony", "Steve", "John"]
|
42
|
+
},
|
43
|
+
{
|
44
|
+
"name": "Last Name",
|
45
|
+
"type": "faker:name:last_name", <- via Faker::Name.last_name method
|
46
|
+
"inject": ["Lu", "Smith"] <- "must-have" values
|
47
|
+
},
|
48
|
+
{
|
49
|
+
"name": "City",
|
50
|
+
"type": "faker:address:city", <- via Faker::Address.city method
|
51
|
+
"rotate": "rows/5" <- rows/5 (=>200/5 =>40) unique values
|
52
|
+
(and only these values) will appear
|
53
|
+
},
|
54
|
+
{
|
55
|
+
"name": "State",
|
56
|
+
"type": "faker:address:state_abbr",
|
57
|
+
"rotate": 10, <- both rotate and inject? will make sure 10 unique
|
58
|
+
values (including "CA") appear
|
59
|
+
"inject": ["CA"]
|
60
|
+
},
|
61
|
+
{
|
62
|
+
"name": "Age",
|
63
|
+
"type": "rand:int",
|
64
|
+
"range": [10, 80] <- range (including boundaries) for random integers
|
65
|
+
},
|
66
|
+
{
|
67
|
+
"name": "Height",
|
68
|
+
"type": "rand:float",
|
69
|
+
"range": [150, 190], <- range for random floats
|
70
|
+
"inject": [200, 210], <- "must-have" values. can be any format
|
71
|
+
"rotate": 20, <- 20 unique values (including injects)
|
72
|
+
"precision": 2 <- precision of the float numbers
|
73
|
+
}
|
74
|
+
]
|
75
|
+
}
|
76
|
+
```
|
77
|
+
|
78
|
+
With the `<name>.csv.json` file, now you can generate a random CSV by invoking the following command:
|
79
|
+
|
80
|
+
```
|
81
|
+
faked_csv -i example.csv.json -o example.csv
|
82
|
+
```
|
83
|
+
|
84
|
+
The output CSV looks something like:
|
85
|
+
|
86
|
+
```
|
87
|
+
ID,First Name,Last Name,City,State,Age,Height
|
88
|
+
iW00K,Jane,Bosco,Lake Dandreland,ME,61,170.57
|
89
|
+
BzxTl,Steve,Smith,Uniqueside,PA,35,152.93
|
90
|
+
vobj8,Tony,Auer,Tressiestad,MS,63,160.86
|
91
|
+
X78RS,Steve,Cole,Port Zellachester,OH,72,159.84
|
92
|
+
0YpWG,John,Lu,East Vernaview,OH,18,200
|
93
|
+
4JaoZ,Peter,Simonis,Wernerchester,HI,25,161.64
|
94
|
+
hP48C,Tom,Lu,Uniqueside,ME,45,161.64
|
95
|
+
WDQpb,John,Casper,East Felicityshire,OH,41,170.57
|
96
|
+
wyPwB,Jane,Johns,Maggiehaven,CA,16,180.42
|
97
|
+
VCtYR,Peter,Jast,Schadenberg,ME,41,161.64
|
98
|
+
1VYOs,John,Daniel,Port Zellachester,HI,34,200
|
99
|
+
V7pg9,Tom,Mayert,Schadenberg,OH,71,152.93
|
100
|
+
SmE9w,Jane,Lu,Stephanchester,HI,25,176.95
|
101
|
+
ALyok,Tom,Smith,Ryanchester,PA,70,176.95
|
102
|
+
fgE5v,Peter,Bailey,Bednarstad,PA,67,170.24
|
103
|
+
eBIIM,Peter,Haley,East Vernaview,MS,65,161.64
|
104
|
+
5sv4L,Peter,Prosacco,Uniqueside,PA,50,178.25
|
105
|
+
a48IS,Peter,Marvin,Kossview,OH,63,200
|
106
|
+
9mLcZ,John,VonRueden,East Vernaview,PA,20,174.24
|
107
|
+
N8ysZ,Tony,Barrows,Wernerchester,HI,62,159.84
|
108
|
+
PxsfA,John,Lind,East Vernaview,OH,21,182.45
|
109
|
+
lKM33,Steve,Bosco,South Reese,OH,75,176.95
|
110
|
+
HR9H5,Jane,Torp,Tressiestad,PA,23,170.57
|
111
|
+
JTRCw,Steve,Hermann,Kunzefort,MS,43,152.93
|
112
|
+
Wndzb,Tony,McGlynn,Lake Dandreland,CA,52,160.86
|
113
|
+
ksmvF,Peter,Rutherford,Josiannetown,PA,12,184.08
|
114
|
+
cfsBG,Peter,Lebsack,Port Zellachester,OH,43,182.45
|
115
|
+
7ISEJ,Steve,Altenwerth,Stephanchester,HI,13,159.84
|
116
|
+
Letb8,John,Frami,South Reese,HI,65,170.57
|
117
|
+
......
|
118
|
+
```
|
119
|
+
|
120
|
+
## CLI Options
|
121
|
+
|
122
|
+
`-i` to specify the input json configuration file. If omitted, the program will try to find `./faked.csv.json` by default. You can also specify a remote URL of the configuration file.
|
123
|
+
|
124
|
+
```
|
125
|
+
faked_csv -i http://goo.gl/xDtkJs -o remote.csv
|
126
|
+
```
|
127
|
+
|
128
|
+
`-o` to specify the output CSV file path. If omitted, the program will print the data to stdout.
|
129
|
+
|
130
|
+
## More details on configuration file
|
131
|
+
|
132
|
+
`rows` to specify how many rows you want to generate in the output CSV file.
|
133
|
+
|
134
|
+
`fields` to specify the list of all fields of the generated CSV file.
|
135
|
+
|
136
|
+
```
|
137
|
+
{
|
138
|
+
"rows": 1000,
|
139
|
+
"fields": [
|
140
|
+
...
|
141
|
+
]
|
142
|
+
}
|
143
|
+
```
|
144
|
+
|
145
|
+
For each field, two attributes are required:
|
146
|
+
|
147
|
+
`name` to specify the column display name.
|
148
|
+
|
149
|
+
`type` to sepcify the format of the data in this column.
|
150
|
+
|
151
|
+
Optional attributes help finer control the generated output.
|
152
|
+
|
153
|
+
`inject` to specify a list of values that must appear in this column. this is useful when you want to specifically inject some special values into your final CSV. The inject values can be in the same or different format as the type of this column.
|
154
|
+
|
155
|
+
`rotate` to specify the number of unique values that will be used in this column. This number will include the number of items you put into `inject` list.
|
156
|
+
|
157
|
+
```
|
158
|
+
"type": "faker:address:state_abbr",
|
159
|
+
"inject": ["CA", "HI"],
|
160
|
+
"rotate": 10
|
161
|
+
```
|
162
|
+
|
163
|
+
In the above example, totally 10 states will be considered in the generation process. 2 of them are given by you, i.e. CA and HI; 8 of them will be faked by calling Faker::Address.state_abbr() method. If you specify `rows` to be greater than 10, some values will be repeated, meaning only 10 unique values will appear and these 10 values are ensured to appear at least once. If you specify `rows` less than 10, only `rows` number of unique values will appear; and your `inject` values will have higher priority, meaning if `rows` is 2, then only CA and HI will appear in the final output.
|
164
|
+
|
165
|
+
### Supported types
|
166
|
+
|
167
|
+
#### rand:int and rand:float
|
168
|
+
|
169
|
+
Random integers/floats. The following attributes are available:
|
170
|
+
|
171
|
+
`range` to specify the minimum and maximum value that will be generated.
|
172
|
+
|
173
|
+
```
|
174
|
+
"range": [10, 100] <- the min=10 and max=100. 10 and 100 are included.
|
175
|
+
```
|
176
|
+
|
177
|
+
If it's `rand:float`, you can specify `precision` attribute to indicate the digit(s) you want to keep for each of the data.
|
178
|
+
|
179
|
+
#### rand:char
|
180
|
+
|
181
|
+
Random characters. Only A-Z, a-z and 0-9 will be considered as characters.
|
182
|
+
|
183
|
+
`length` to specify how many characters in each of the generated data, e.g. 15 will give you something like `9mLcZHR9H5V7pg9`. This is particularly useful if you want to mimic something like item ID, access token etc.
|
184
|
+
|
185
|
+
#### faker:[class]:[method]
|
186
|
+
|
187
|
+
This indicates you want to use one of the methods from Faker gem. You can find the list of all methods from [Faker gem's documentation](http://rubydoc.info/github/stympy/faker). Each method is a class name and a method name. Example, `Faker::Internet.url` can be mapped to `faker:internet:url` as a field type in the configuration. As current version, we don't support parameters into the faker method. Future version will add such support.
|
188
|
+
|
189
|
+
#### fixed
|
190
|
+
|
191
|
+
This indicates you only want to use the provided values in the output. Use `values` as a list to provide the values you want to use. They will be randomly picked independently each time; so no guarantee that every value in the list will be used. If you use `fixed` type, `inject` and `rotate` will be ignored.
|
192
|
+
|
193
|
+
## Contributing
|
194
|
+
|
195
|
+
1. Fork it ( https://github.com/jiananlu/faked_csv/fork )
|
196
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
197
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
198
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
199
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/bin/faked_csv
ADDED
data/example.csv.json
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
{
|
2
|
+
"rows": 200,
|
3
|
+
"fields": [
|
4
|
+
{
|
5
|
+
"name": "ID",
|
6
|
+
"type": "rand:char",
|
7
|
+
"length": 5
|
8
|
+
},
|
9
|
+
{
|
10
|
+
"name": "First Name",
|
11
|
+
"type": "fixed",
|
12
|
+
"values": ["Peter", "Tom", "Jane", "Tony", "Steve", "John"]
|
13
|
+
},
|
14
|
+
{
|
15
|
+
"name": "Last Name",
|
16
|
+
"type": "faker:name:last_name",
|
17
|
+
"inject": ["Lu", "Smith"]
|
18
|
+
},
|
19
|
+
{
|
20
|
+
"name": "City",
|
21
|
+
"type": "faker:address:city",
|
22
|
+
"rotate": "rows/5"
|
23
|
+
},
|
24
|
+
{
|
25
|
+
"name": "State",
|
26
|
+
"type": "faker:address:state_abbr",
|
27
|
+
"rotate": 10,
|
28
|
+
"inject": ["CA"]
|
29
|
+
},
|
30
|
+
{
|
31
|
+
"name": "Age",
|
32
|
+
"type": "rand:int",
|
33
|
+
"range": [10, 80]
|
34
|
+
},
|
35
|
+
{
|
36
|
+
"name": "Height",
|
37
|
+
"type": "rand:float",
|
38
|
+
"range": [150, 190],
|
39
|
+
"inject": [200, 210],
|
40
|
+
"rotate": 20,
|
41
|
+
"precision": 2
|
42
|
+
}
|
43
|
+
]
|
44
|
+
}
|
data/faked_csv.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'faked_csv/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "faked_csv"
|
8
|
+
spec.version = FakedCSV::VERSION
|
9
|
+
spec.authors = ["Jianan Lu"]
|
10
|
+
spec.email = ["jianan.lu@salesforce.com"]
|
11
|
+
spec.summary = %q{Generate faked CSV data in the specified way.}
|
12
|
+
spec.description = %q{Makes generating CSV file with faked, random data easy to do.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.3"
|
23
|
+
spec.add_development_dependency "rspec", "~> 2.14"
|
24
|
+
spec.add_development_dependency "cucumber", "~> 1.3"
|
25
|
+
spec.add_development_dependency "aruba", "~> 0.5"
|
26
|
+
spec.add_development_dependency "byebug", "~> 3.1"
|
27
|
+
|
28
|
+
spec.add_dependency "faker", "~> 1.3"
|
29
|
+
spec.add_dependency "json", "~> 1.8"
|
30
|
+
spec.add_dependency "open_uri_redirections", "~> 0.1"
|
31
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
Feature: faked_csv CLI program
|
2
|
+
|
3
|
+
Scenario: Show help message
|
4
|
+
When I run `faked_csv -h`
|
5
|
+
Then the output should contain "Usage: faked_csv -i <input.csv.json> -o <output.csv>"
|
6
|
+
|
7
|
+
Scenario: Show version
|
8
|
+
When I run `faked_csv --version`
|
9
|
+
Then the output should contain "version:"
|
10
|
+
|
11
|
+
Scenario: Generate basic csv
|
12
|
+
When I run `faked_csv -i ../../spec/data/basic.csv.json -o output.csv`
|
13
|
+
Then the output should contain exactly ""
|
14
|
+
And the file "output.csv" should contain "ID,First Name,Last Name,City,State,Age,Height"
|
15
|
+
|
16
|
+
Scenario: Generate basic csv and print to stdout
|
17
|
+
When I run `faked_csv -i ../../spec/data/basic.csv.json`
|
18
|
+
Then the output should contain "ID,First Name,Last Name,City,State,Age,Height"
|
19
|
+
|
20
|
+
Scenario: Find no default files
|
21
|
+
When I run `faked_csv`
|
22
|
+
Then the output should contain "error openning the input source: No such file or directory"
|
23
|
+
And the output should contain "./faked.csv.json"
|
24
|
+
|
25
|
+
Scenario: Getting from HTTP
|
26
|
+
When I run `faked_csv -i http://goo.gl/xDtkJs -o remote.csv`
|
27
|
+
Then the output should contain exactly ""
|
28
|
+
And the file "remote.csv" should contain "ID,First Name,Last Name,City,State,Age,Height"
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'aruba/cucumber'
|
data/lib/faked_csv.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'json'
|
3
|
+
require 'open-uri'
|
4
|
+
require 'open_uri_redirections'
|
5
|
+
require 'faked_csv'
|
6
|
+
|
7
|
+
module FakedCSV
|
8
|
+
class CLI
|
9
|
+
def self.start(args)
|
10
|
+
options = {}
|
11
|
+
OptionParser.new do |opts|
|
12
|
+
opts.banner = "Usage: faked_csv -i <input.csv.json> -o <output.csv>"
|
13
|
+
opts.on("-i", "--input JSON", "input path to json configuration file. default: ./faked.csv.json") do |input|
|
14
|
+
options[:input] = input
|
15
|
+
end
|
16
|
+
opts.on("-o", "--output CSV", "output path to csv file. if omit, print to STDOUT") do |output|
|
17
|
+
options[:output] = output
|
18
|
+
end
|
19
|
+
opts.on("-v", "--version", "print version message") do
|
20
|
+
puts "version: #{VERSION}"
|
21
|
+
return
|
22
|
+
end
|
23
|
+
end.parse!(args)
|
24
|
+
|
25
|
+
options[:input] = './faked.csv.json' unless options.has_key? :input
|
26
|
+
|
27
|
+
json = nil
|
28
|
+
begin
|
29
|
+
if options[:input] =~ /^http/
|
30
|
+
# remote resouce
|
31
|
+
open(options[:input], allow_redirections: :all) do |f|
|
32
|
+
arr = []
|
33
|
+
f.each_line {|line| arr << line}
|
34
|
+
json = arr.join("\n")
|
35
|
+
end
|
36
|
+
else
|
37
|
+
# normal file
|
38
|
+
json = File.read options[:input]
|
39
|
+
end
|
40
|
+
rescue Exception=>e
|
41
|
+
puts "error openning the input source: #{e.to_s}"
|
42
|
+
exit 1
|
43
|
+
end
|
44
|
+
|
45
|
+
generator = FakedCSV::Generator.new FakedCSV::Config.new JSON.parse json
|
46
|
+
generator.generate
|
47
|
+
printer = FakedCSV::Printer.new(generator.headers, generator.rows)
|
48
|
+
s = printer.print
|
49
|
+
|
50
|
+
unless options.has_key? :output
|
51
|
+
puts s
|
52
|
+
return
|
53
|
+
end
|
54
|
+
|
55
|
+
begin
|
56
|
+
File.open options[:output], 'w' do |f|
|
57
|
+
f.write s
|
58
|
+
end
|
59
|
+
rescue Exception=>e
|
60
|
+
puts "error writing to csv file: #{e.to_s}"
|
61
|
+
exit 2
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module FakedCSV
|
2
|
+
class Config
|
3
|
+
attr_reader :config, :fields, :row_count
|
4
|
+
|
5
|
+
def initialize(config)
|
6
|
+
@config = config
|
7
|
+
end
|
8
|
+
|
9
|
+
def fields
|
10
|
+
parse if @fields.nil? # parse first if not parsed yet
|
11
|
+
@fields
|
12
|
+
end
|
13
|
+
|
14
|
+
def headers
|
15
|
+
fields.map{|f| f[:name]}
|
16
|
+
end
|
17
|
+
|
18
|
+
# prepare the json config and generate the fields
|
19
|
+
def parse
|
20
|
+
if @config["rows"].nil? || @config["rows"].to_i < 0
|
21
|
+
@row_count = 100 # default value
|
22
|
+
else
|
23
|
+
@row_count = @config["rows"].to_i
|
24
|
+
end
|
25
|
+
|
26
|
+
@fields = []
|
27
|
+
if @config["fields"].nil? || @config["fields"].empty?
|
28
|
+
raise "need 'fields' in the config file and at least 1 field in it"
|
29
|
+
end
|
30
|
+
|
31
|
+
@config["fields"].each do |cfg|
|
32
|
+
field = {}
|
33
|
+
|
34
|
+
if cfg["name"].nil?
|
35
|
+
raise "field needs a name"
|
36
|
+
end
|
37
|
+
field[:name] = cfg["name"].to_s
|
38
|
+
|
39
|
+
if cfg["type"].nil? || cfg["type"].empty?
|
40
|
+
raise "field needs a type"
|
41
|
+
end
|
42
|
+
field[:type] = cfg["type"].to_s
|
43
|
+
|
44
|
+
unless cfg["inject"].nil? || cfg["inject"].empty? || !cfg["inject"].kind_of?(Array)
|
45
|
+
field[:inject] = cfg["inject"].uniq # get rid of duplicates
|
46
|
+
end
|
47
|
+
|
48
|
+
unless cfg["rotate"].nil?
|
49
|
+
field[:rotate] = _validate_rotate cfg["rotate"]
|
50
|
+
end
|
51
|
+
|
52
|
+
case field[:type]
|
53
|
+
when /rand:int/i
|
54
|
+
field[:type] = :rand_int
|
55
|
+
if cfg["range"].nil?
|
56
|
+
# no range specified? use the default range: [0, 100]
|
57
|
+
field[:min], field[:max] = 0, 100
|
58
|
+
else
|
59
|
+
field[:min], field[:max] = _min_max cfg["range"]
|
60
|
+
end
|
61
|
+
when /rand:float/i
|
62
|
+
field[:type] = :rand_float
|
63
|
+
if cfg["range"].nil?
|
64
|
+
# no range specified? use the default range: [0, 1]
|
65
|
+
field[:min], field[:max] = 0, 1
|
66
|
+
else
|
67
|
+
field[:min], field[:max] = _min_max cfg["range"]
|
68
|
+
end
|
69
|
+
field[:precision] = cfg["precision"].nil? ? 1 : cfg["precision"].to_i
|
70
|
+
when /rand:char/i
|
71
|
+
field[:type] = :rand_char
|
72
|
+
field[:length] = cfg["length"].nil? ? 10 : cfg["length"]
|
73
|
+
when /fixed/i
|
74
|
+
field[:type] = :fixed
|
75
|
+
raise "need values for fixed type" if cfg["values"].nil?
|
76
|
+
field[:values] = cfg["values"]
|
77
|
+
when /faker:\S+/i
|
78
|
+
field[:type] = cfg["type"]
|
79
|
+
else
|
80
|
+
raise "unsupported type: #{field[:type]}. supported types: #{_supported_types}"
|
81
|
+
end
|
82
|
+
|
83
|
+
fields << field
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def _supported_types
|
88
|
+
['rand:int', 'rand:float', 'rand:char', 'fixed', 'faker:<class>:<method>'].join ", "
|
89
|
+
end
|
90
|
+
|
91
|
+
def _min_max(range)
|
92
|
+
unless range.kind_of?(Array) && range.size == 2
|
93
|
+
raise "invalid range. should be like: [0, 100]"
|
94
|
+
end
|
95
|
+
if range[0] >= range[1]
|
96
|
+
raise "invalid range. 1st is >= 2nd"
|
97
|
+
end
|
98
|
+
return range[0], range[1]
|
99
|
+
end
|
100
|
+
|
101
|
+
def _validate_rotate(rotate)
|
102
|
+
if rotate.to_s.include? "rows/"
|
103
|
+
div = rotate.split("/")[1].to_i
|
104
|
+
r = @row_count / div
|
105
|
+
else
|
106
|
+
r = rotate.to_i
|
107
|
+
end
|
108
|
+
return r > @row_count ? @row_count : r
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'faker'
|
2
|
+
|
3
|
+
# skip validation of locales
|
4
|
+
I18n.enforce_available_locales = false
|
5
|
+
|
6
|
+
module FakedCSV
|
7
|
+
class Fakerer
|
8
|
+
attr_reader :type
|
9
|
+
def initialize(type)
|
10
|
+
@type = type
|
11
|
+
faker, class_name, @method = @type.split ':'
|
12
|
+
begin
|
13
|
+
@class = Kernel.const_get("Faker::#{_camelize class_name}")
|
14
|
+
rescue
|
15
|
+
raise "unsupported faker class: #{class_name}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def fake
|
20
|
+
begin
|
21
|
+
@class.send @method
|
22
|
+
rescue
|
23
|
+
raise "unsupported faker method: #{@method}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def _camelize(str)
|
28
|
+
str.split('_').map {|w| w.capitalize}.join
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
module FakedCSV
|
2
|
+
class Generator
|
3
|
+
attr_reader :config, :rows
|
4
|
+
|
5
|
+
def initialize(config)
|
6
|
+
@config = config
|
7
|
+
end
|
8
|
+
|
9
|
+
def headers
|
10
|
+
@config.headers
|
11
|
+
end
|
12
|
+
|
13
|
+
def rows
|
14
|
+
return @rows unless @rows.nil?
|
15
|
+
@rows = []
|
16
|
+
(0...@config.row_count).each do |r|
|
17
|
+
row = []
|
18
|
+
@config.fields.each do |field|
|
19
|
+
row << field[:data][r]
|
20
|
+
end
|
21
|
+
@rows << row
|
22
|
+
end
|
23
|
+
@rows
|
24
|
+
end
|
25
|
+
|
26
|
+
def generate
|
27
|
+
prepare_values
|
28
|
+
|
29
|
+
@config.fields.each do |field|
|
30
|
+
field[:data] = []
|
31
|
+
|
32
|
+
# let's get some data!
|
33
|
+
if field[:rotate].nil? || field[:type] == :fixed
|
34
|
+
# not rotating? or fixed values? generate random value each time
|
35
|
+
@config.row_count.times do
|
36
|
+
field[:data] << _random_value(field)
|
37
|
+
end
|
38
|
+
|
39
|
+
# inject user values if given and not fixed type
|
40
|
+
unless field[:type] == :fixed || field[:inject].nil?
|
41
|
+
_random_inject(field[:data], field[:inject])
|
42
|
+
end
|
43
|
+
else
|
44
|
+
# rotating? pick from prepared values
|
45
|
+
_random_distribution(@config.row_count, field[:values].size) do |i, j|
|
46
|
+
field[:data][i] = field[:values][j]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def prepare_values
|
53
|
+
@config.fields.each do |field|
|
54
|
+
# if it's fixed values or no rotate
|
55
|
+
# we don't want to prepare values for this field
|
56
|
+
if field[:type] == :fixed || field[:rotate].nil?
|
57
|
+
next
|
58
|
+
end
|
59
|
+
|
60
|
+
# we don't have enough integers for the rotate
|
61
|
+
if field[:type] == :rand_int && field[:rotate] > field[:max] - field[:min] + 1
|
62
|
+
raise "rotate should not be greater than the size of the range"
|
63
|
+
end
|
64
|
+
|
65
|
+
values = {}
|
66
|
+
# let's first inject all user values if given
|
67
|
+
unless field[:inject].nil?
|
68
|
+
field[:inject].each do |inj|
|
69
|
+
values[inj] = true
|
70
|
+
# truncate more inject values if we go over the rows count
|
71
|
+
break if values.size == @config.row_count
|
72
|
+
end
|
73
|
+
end
|
74
|
+
# then generate as many data as we need
|
75
|
+
_loop do
|
76
|
+
# we want to get <rotate> unique values. stop when we got enough
|
77
|
+
break if values.size >= field[:rotate]
|
78
|
+
v = _random_value(field)
|
79
|
+
values[v] = true
|
80
|
+
end
|
81
|
+
field[:values] = values.keys
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def _random_distribution(total, parts)
|
86
|
+
raise "parts has to be greater than 0" unless parts > 0
|
87
|
+
raise "parts should not be greater than total" if total < parts
|
88
|
+
cuts = {}
|
89
|
+
_loop do
|
90
|
+
break if cuts.size == parts - 1
|
91
|
+
cuts[rand(total - 1)] = true
|
92
|
+
end
|
93
|
+
arr = []
|
94
|
+
part_index = 0
|
95
|
+
(0...total).each do |i|
|
96
|
+
arr << part_index
|
97
|
+
part_index += 1 if cuts.has_key? i
|
98
|
+
end
|
99
|
+
arr.shuffle.each_with_index do |v, i|
|
100
|
+
yield(i, v)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# inject <injects> into <values>
|
105
|
+
def _random_inject(values, injects)
|
106
|
+
used_indexes = {}
|
107
|
+
count = injects.size > values.size ? values.size : injects.size
|
108
|
+
(0...count).each do |i|
|
109
|
+
inj = injects[i]
|
110
|
+
times_inject = rand(values.size / injects.size / 10)
|
111
|
+
times_inject = 1 if times_inject < 1
|
112
|
+
times_inject.times do
|
113
|
+
rand_index = rand(values.size)
|
114
|
+
_loop do
|
115
|
+
break unless used_indexes.has_key? rand_index
|
116
|
+
rand_index = rand(values.size)
|
117
|
+
end
|
118
|
+
used_indexes[rand_index] = true
|
119
|
+
values[rand_index] = inj
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def _random_value(field)
|
125
|
+
case field[:type]
|
126
|
+
when :rand_int
|
127
|
+
return Generator.rand_int field[:min], field[:max]
|
128
|
+
when :rand_float
|
129
|
+
return Generator.rand_float field[:min], field[:max], field[:precision]
|
130
|
+
when :rand_char
|
131
|
+
return Generator.rand_char field[:length]
|
132
|
+
when :fixed
|
133
|
+
return field[:values].sample
|
134
|
+
else # faker
|
135
|
+
return Generator.fake field[:type]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def _loop
|
140
|
+
max_attempts = 1000_000_000_000
|
141
|
+
i = 0
|
142
|
+
(0...max_attempts).each do |j|
|
143
|
+
yield
|
144
|
+
i += 1
|
145
|
+
end
|
146
|
+
raise "max attempts reached" if i == max_attempts
|
147
|
+
end
|
148
|
+
|
149
|
+
## individual random generators
|
150
|
+
|
151
|
+
def self.rand_char(length)
|
152
|
+
o = [('a'..'z'), ('A'..'Z'), (0..9)].map { |i| i.to_a }.flatten
|
153
|
+
string = (0...length).map { o[rand(o.length)] }.join
|
154
|
+
end
|
155
|
+
|
156
|
+
def self.rand_int(min, max)
|
157
|
+
raise "min > max" if min > max
|
158
|
+
min + rand(max - min + 1)
|
159
|
+
end
|
160
|
+
|
161
|
+
def self.rand_float(min, max, precision)
|
162
|
+
raise "min > max" if min > max
|
163
|
+
(rand * (max - min) + min).round(precision)
|
164
|
+
end
|
165
|
+
|
166
|
+
def self.fake(type)
|
167
|
+
Fakerer.new(type).fake
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FakedCSV::Config do
|
4
|
+
it "parses the basic json config" do
|
5
|
+
json = JSON.parse File.read 'spec/data/basic.csv.json'
|
6
|
+
config = FakedCSV::Config.new json
|
7
|
+
config.config["rows"].should == 200
|
8
|
+
config.parse
|
9
|
+
config.row_count.should == 200
|
10
|
+
config.fields.should == [
|
11
|
+
{:name=>"ID", :type=>:rand_char, :length=>5},
|
12
|
+
{:name=>"First Name", :type=>:fixed, :values=>["Peter", "Tom", "Jane", "Tony", "Steve", "John"]},
|
13
|
+
{:name=>"Last Name", :type=>"faker:name:last_name", :inject=>["Lu", "Smith"]},
|
14
|
+
{:name=>"City", :type=>"faker:address:city", :rotate=>40},
|
15
|
+
{:name=>"State", :type=>"faker:address:state_abbr", :inject=>["CA"], :rotate=>10},
|
16
|
+
{:name=>"Age", :type=>:rand_int, :min=>10, :max=>80},
|
17
|
+
{:name=>"Height", :type=>:rand_float, :inject=>[200, 210], :rotate=>20, :min=>150, :max=>190, :precision=>2}
|
18
|
+
]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "provides fields headers" do
|
22
|
+
json = JSON.parse File.read 'spec/data/basic.csv.json'
|
23
|
+
config = FakedCSV::Config.new json
|
24
|
+
config.headers.should == ["ID", "First Name", "Last Name", "City", "State", "Age", "Height"]
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
{
|
2
|
+
"rows": 200,
|
3
|
+
"fields": [
|
4
|
+
{
|
5
|
+
"name": "ID",
|
6
|
+
"type": "rand:char",
|
7
|
+
"length": 5
|
8
|
+
},
|
9
|
+
{
|
10
|
+
"name": "First Name",
|
11
|
+
"type": "fixed",
|
12
|
+
"values": ["Peter", "Tom", "Jane", "Tony", "Steve", "John"]
|
13
|
+
},
|
14
|
+
{
|
15
|
+
"name": "Last Name",
|
16
|
+
"type": "faker:name:last_name",
|
17
|
+
"inject": ["Lu", "Smith"]
|
18
|
+
},
|
19
|
+
{
|
20
|
+
"name": "City",
|
21
|
+
"type": "faker:address:city",
|
22
|
+
"rotate": "rows/5"
|
23
|
+
},
|
24
|
+
{
|
25
|
+
"name": "State",
|
26
|
+
"type": "faker:address:state_abbr",
|
27
|
+
"rotate": 10,
|
28
|
+
"inject": ["CA"]
|
29
|
+
},
|
30
|
+
{
|
31
|
+
"name": "Age",
|
32
|
+
"type": "rand:int",
|
33
|
+
"range": [10, 80]
|
34
|
+
},
|
35
|
+
{
|
36
|
+
"name": "Height",
|
37
|
+
"type": "rand:float",
|
38
|
+
"range": [150, 190],
|
39
|
+
"inject": [200, 210],
|
40
|
+
"rotate": 20,
|
41
|
+
"precision": 2
|
42
|
+
}
|
43
|
+
]
|
44
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
{
|
2
|
+
"rows": 10,
|
3
|
+
"fields": [
|
4
|
+
{
|
5
|
+
"name": "faker no rotate",
|
6
|
+
"type": "faker:name:first_name"
|
7
|
+
},
|
8
|
+
{
|
9
|
+
"name": "faker with rotate",
|
10
|
+
"type": "faker:name:first_name",
|
11
|
+
"rotate": 10
|
12
|
+
},
|
13
|
+
{
|
14
|
+
"name": "faker with rotate and inject",
|
15
|
+
"type": "faker:name:first_name",
|
16
|
+
"rotate": 10,
|
17
|
+
"inject": ["aaa", "bbb"]
|
18
|
+
},
|
19
|
+
|
20
|
+
{
|
21
|
+
"name": "rand int no rotate",
|
22
|
+
"type": "rand:int"
|
23
|
+
},
|
24
|
+
{
|
25
|
+
"name": "rand int with rotate",
|
26
|
+
"type": "rand:int",
|
27
|
+
"rotate": 10
|
28
|
+
},
|
29
|
+
{
|
30
|
+
"name": "rand int with rotate and inject",
|
31
|
+
"type": "rand:int",
|
32
|
+
"rotate": 10,
|
33
|
+
"inject": [11, 12, 13]
|
34
|
+
}
|
35
|
+
]
|
36
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FakedCSV::Fakerer do
|
4
|
+
it "validates input type" do
|
5
|
+
FakedCSV::Fakerer.new("faker:name:last_name").fake.size.should > 1
|
6
|
+
end
|
7
|
+
|
8
|
+
it "invalidates input type: class" do
|
9
|
+
raised = false
|
10
|
+
begin
|
11
|
+
f = FakedCSV::Fakerer.new("faker:name1:last_name")
|
12
|
+
rescue
|
13
|
+
raised = true
|
14
|
+
end
|
15
|
+
raise "not raised invalid faker class" unless raised
|
16
|
+
end
|
17
|
+
|
18
|
+
it "invalidates input type: method" do
|
19
|
+
raised = false
|
20
|
+
f = FakedCSV::Fakerer.new("faker:name:last_name1")
|
21
|
+
begin
|
22
|
+
f.fake_single
|
23
|
+
rescue
|
24
|
+
raised = true
|
25
|
+
end
|
26
|
+
raise "not raised invalid faker method" unless raised
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FakedCSV::Generator do
|
4
|
+
it "generates rand char" do
|
5
|
+
FakedCSV::Generator.rand_char(1).size.should == 1
|
6
|
+
FakedCSV::Generator.rand_char(10).size.should == 10
|
7
|
+
FakedCSV::Generator.rand_char(100).size.should == 100
|
8
|
+
end
|
9
|
+
|
10
|
+
it "generates rand int" do
|
11
|
+
1000.times do
|
12
|
+
i = FakedCSV::Generator.rand_int(0, 10)
|
13
|
+
i.should <= 10
|
14
|
+
i.should >= 0
|
15
|
+
end
|
16
|
+
FakedCSV::Generator.rand_int(0, 0).should == 0
|
17
|
+
raised = false
|
18
|
+
begin
|
19
|
+
FakedCSV::Generator.rand_int(1, 0).should == 0
|
20
|
+
rescue
|
21
|
+
raised = true
|
22
|
+
end
|
23
|
+
raise "not raised the min > max exception" unless raised
|
24
|
+
1000.times do
|
25
|
+
i = FakedCSV::Generator.rand_int(-10, 0)
|
26
|
+
i.should <= 0
|
27
|
+
i.should >= -10
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "generates rand float" do
|
32
|
+
1000.times do
|
33
|
+
i = FakedCSV::Generator.rand_float(0, 10, 2)
|
34
|
+
i.should <= 10
|
35
|
+
i.should >= 0
|
36
|
+
end
|
37
|
+
FakedCSV::Generator.rand_float(0, 0, 0).should == 0
|
38
|
+
raised = false
|
39
|
+
begin
|
40
|
+
FakedCSV::Generator.rand_float(1, 0, 2).should == 0
|
41
|
+
rescue
|
42
|
+
raised = true
|
43
|
+
end
|
44
|
+
raise "not raised the min > max exception" unless raised
|
45
|
+
1000.times do
|
46
|
+
i = FakedCSV::Generator.rand_float(-10, 0, 10)
|
47
|
+
i.should <= 0
|
48
|
+
i.should >= -10
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it "generates faker data" do
|
53
|
+
FakedCSV::Generator.fake("faker:name:last_name").size.should > 1
|
54
|
+
end
|
55
|
+
|
56
|
+
it "prepare values for rotate fields" do
|
57
|
+
generator = FakedCSV::Generator.new FakedCSV::Config.new JSON.parse File.read 'spec/data/rotate.csv.json'
|
58
|
+
generator.prepare_values
|
59
|
+
f = generator.config.fields
|
60
|
+
f[0].should == {:name=>"faker no rotate", :type=>"faker:name:first_name"}
|
61
|
+
f[1][:rotate].should == 10
|
62
|
+
f[1][:values].size.should == 10
|
63
|
+
f[2][:rotate].should == 10
|
64
|
+
f[2][:values].size.should == 10
|
65
|
+
f[2][:inject].should == ["aaa", "bbb"]
|
66
|
+
f[3].should == {:name=>"rand int no rotate", :type=>:rand_int, :min=>0, :max=>100}
|
67
|
+
f[4][:rotate].should == 10
|
68
|
+
f[4][:values].size.should == 10
|
69
|
+
f[5][:rotate].should == 10
|
70
|
+
f[5][:values].size.should == 10
|
71
|
+
f[5][:inject].should == [11, 12, 13]
|
72
|
+
end
|
73
|
+
|
74
|
+
it "generates random data" do
|
75
|
+
generator = FakedCSV::Generator.new FakedCSV::Config.new JSON.parse File.read 'spec/data/rotate.csv.json'
|
76
|
+
generator.generate
|
77
|
+
f = generator.config.fields
|
78
|
+
f[0][:data].size.should == 10
|
79
|
+
f[1][:data].size.should == 10
|
80
|
+
f[1][:data].each do |d|
|
81
|
+
f[1][:values].include?(d).should == true
|
82
|
+
end
|
83
|
+
f[2][:data].each do |d|
|
84
|
+
(f[2][:values].include?(d) || f[2][:values].include?(d)).should == true
|
85
|
+
end
|
86
|
+
f[3][:data].size.should == 10
|
87
|
+
f[4][:data].size.should == 10
|
88
|
+
f[4][:data].each do |d|
|
89
|
+
f[4][:values].include?(d).should == true
|
90
|
+
end
|
91
|
+
f[5][:data].each do |d|
|
92
|
+
(f[5][:values].include?(d) || f[5][:values].include?(d)).should == true
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it "generates random data from basic csv" do
|
97
|
+
generator = FakedCSV::Generator.new FakedCSV::Config.new JSON.parse File.read 'spec/data/basic.csv.json'
|
98
|
+
generator.generate
|
99
|
+
f = generator.config.fields
|
100
|
+
f.each{|ff| ff[:data].size.should == 200}
|
101
|
+
f[0][:data].each{|d|d.size.should == 5}
|
102
|
+
f[1][:data].each do |d|
|
103
|
+
f[1][:values].include?(d).should == true
|
104
|
+
end
|
105
|
+
f[1][:data].uniq.size.should == f[1][:values].size
|
106
|
+
f[2][:inject].each do |inj|
|
107
|
+
f[2][:data].include?(inj).should == true
|
108
|
+
end
|
109
|
+
f[3][:data].uniq.size.should == 40
|
110
|
+
f[4][:data].uniq.size.should == 10
|
111
|
+
f[4][:data].include?("CA").should == true
|
112
|
+
f[5][:data].each do |d|
|
113
|
+
d.kind_of?(Integer).should == true
|
114
|
+
(d >= 10 && d <= 80).should == true
|
115
|
+
end
|
116
|
+
f[6][:data].uniq.size.should == 20
|
117
|
+
f[6][:data].include?(200).should == true
|
118
|
+
f[6][:data].include?(210).should == true
|
119
|
+
f[6][:data].each do |d|
|
120
|
+
((d >= 150 && d <= 190) || d == 200 || d == 210).should == true
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
it "provides data as rows" do
|
125
|
+
generator = FakedCSV::Generator.new FakedCSV::Config.new JSON.parse File.read 'spec/data/rotate.csv.json'
|
126
|
+
generator.generate
|
127
|
+
rows = generator.rows
|
128
|
+
rows.size.should == 10
|
129
|
+
rows.each do |row|
|
130
|
+
row.size.should == 6
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
it "handles inject without rotate" do
|
135
|
+
generator = FakedCSV::Generator.new FakedCSV::Config.new JSON.parse File.read 'spec/data/inject.csv.json'
|
136
|
+
generator.generate
|
137
|
+
generator.config.fields[0][:data].include?("aa").should == true
|
138
|
+
generator.config.fields[0][:data].include?("bb").should == true
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FakedCSV::Printer do
|
4
|
+
it "returns csv as string" do
|
5
|
+
generator = FakedCSV::Generator.new FakedCSV::Config.new JSON.parse File.read 'spec/data/rotate.csv.json'
|
6
|
+
generator.generate
|
7
|
+
printer = FakedCSV::Printer.new(generator.headers, generator.rows)
|
8
|
+
s = printer.print
|
9
|
+
s.include?("faker no rotate,").should == true
|
10
|
+
s.include?(",rand int with rotate and inject").should == true
|
11
|
+
s.include?("13").should == true
|
12
|
+
s.include?("aaa").should == true
|
13
|
+
s.include?("bbb").should == true
|
14
|
+
end
|
15
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: faked_csv
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jianan Lu
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-05-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.14'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.14'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: cucumber
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.3'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.3'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: aruba
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.5'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.5'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: byebug
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.1'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.1'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: faker
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.3'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.3'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: json
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.8'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1.8'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: open_uri_redirections
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0.1'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0.1'
|
139
|
+
description: Makes generating CSV file with faked, random data easy to do.
|
140
|
+
email:
|
141
|
+
- jianan.lu@salesforce.com
|
142
|
+
executables:
|
143
|
+
- faked_csv
|
144
|
+
extensions: []
|
145
|
+
extra_rdoc_files: []
|
146
|
+
files:
|
147
|
+
- ".gitignore"
|
148
|
+
- Gemfile
|
149
|
+
- LICENSE.txt
|
150
|
+
- README.md
|
151
|
+
- Rakefile
|
152
|
+
- bin/faked_csv
|
153
|
+
- example.csv.json
|
154
|
+
- faked_csv.gemspec
|
155
|
+
- features/faked_csv.feature
|
156
|
+
- features/support/setup.rb
|
157
|
+
- lib/faked_csv.rb
|
158
|
+
- lib/faked_csv/cli.rb
|
159
|
+
- lib/faked_csv/config.rb
|
160
|
+
- lib/faked_csv/fakerer.rb
|
161
|
+
- lib/faked_csv/generator.rb
|
162
|
+
- lib/faked_csv/printer.rb
|
163
|
+
- lib/faked_csv/version.rb
|
164
|
+
- spec/config_spec.rb
|
165
|
+
- spec/data/basic.csv.json
|
166
|
+
- spec/data/inject.csv.json
|
167
|
+
- spec/data/rotate.csv.json
|
168
|
+
- spec/fakerer_spec.rb
|
169
|
+
- spec/generator_spec.rb
|
170
|
+
- spec/printer_spec.rb
|
171
|
+
- spec/spec_helper.rb
|
172
|
+
homepage: ''
|
173
|
+
licenses:
|
174
|
+
- MIT
|
175
|
+
metadata: {}
|
176
|
+
post_install_message:
|
177
|
+
rdoc_options: []
|
178
|
+
require_paths:
|
179
|
+
- lib
|
180
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
181
|
+
requirements:
|
182
|
+
- - ">="
|
183
|
+
- !ruby/object:Gem::Version
|
184
|
+
version: '0'
|
185
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
186
|
+
requirements:
|
187
|
+
- - ">="
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
190
|
+
requirements: []
|
191
|
+
rubyforge_project:
|
192
|
+
rubygems_version: 2.2.2
|
193
|
+
signing_key:
|
194
|
+
specification_version: 4
|
195
|
+
summary: Generate faked CSV data in the specified way.
|
196
|
+
test_files:
|
197
|
+
- features/faked_csv.feature
|
198
|
+
- features/support/setup.rb
|
199
|
+
- spec/config_spec.rb
|
200
|
+
- spec/data/basic.csv.json
|
201
|
+
- spec/data/inject.csv.json
|
202
|
+
- spec/data/rotate.csv.json
|
203
|
+
- spec/fakerer_spec.rb
|
204
|
+
- spec/generator_spec.rb
|
205
|
+
- spec/printer_spec.rb
|
206
|
+
- spec/spec_helper.rb
|