Skip to content

Commit

Permalink
Merge pull request #3 from cazgp/feat/seed
Browse files Browse the repository at this point in the history
GH-2 Add ability to seed
  • Loading branch information
askn authored Jul 9, 2017
2 parents 8610498 + 284782b commit 4176ac1
Show file tree
Hide file tree
Showing 20 changed files with 228 additions and 52 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ require "faker"
Faker::Name.name
```

### Faker.seed

If you wish to seed the random data, you can call `Faker.seed number` and then all subsequent calls will be deterministic.

### Faker::Address

```crystal
Expand Down
24 changes: 24 additions & 0 deletions spec/address_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require "./spec_helper"

describe Faker::Address do
it "should return deterministic results when seeded" do
Faker.seed 123456
Faker::Address.city.should eq "North Mercedesmouth"
Faker::Address.street_name.should eq "Thalia Tunnel"
Faker::Address.street_address.should eq "33421 Kunde Mills"
Faker::Address.secondary_address.should eq "Apt. 475"
Faker::Address.building_number.should eq "4103"
Faker::Address.zip_code.should eq "32555"
Faker::Address.postcode.should eq "GX44 3IC"
Faker::Address.time_zone.should eq "Asia/Rangoon"
Faker::Address.street_suffix.should eq "Springs"
Faker::Address.city_suffix.should eq "town"
Faker::Address.city_prefix.should eq "North"
Faker::Address.state.should eq "Missouri"
Faker::Address.state_abbr.should eq "TN"
Faker::Address.country.should eq "Svalbard & Jan Mayen Islands"
Faker::Address.country_code.should eq "IS"
Faker::Address.latitude.should eq "15.393888556377334"
Faker::Address.longitude.should eq "-77.86301819889268"
end
end
10 changes: 10 additions & 0 deletions spec/business_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require "./spec_helper"

describe Faker::Business do
it "should return deterministic results when seeded" do
Faker.seed 123456
Faker::Business.credit_card_number.should eq "1234-2121-1221-1211"
Faker::Business.credit_card_expiry_date.should eq Time.new(2013, 9, 12)
Faker::Business.credit_card_type.should eq "diners_club"
end
end
11 changes: 11 additions & 0 deletions spec/commerce_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,15 @@ describe Faker::Commerce do
it "price_is_float" do
Faker::Commerce.price.is_a?(Float).should be_true
end

it "should return deterministic results when seeded" do
Faker.seed 123456
Faker::Commerce.color.should eq "salmon"
Faker::Commerce.department.should eq "Home, Movies & Computers"
Faker::Commerce.department(5).should eq "Toys & Home"
Faker::Commerce.department(2, true).should eq "Electronics & Tools"
Faker::Commerce.product_name.should eq "Heavy Duty Copper Lamp"
Faker::Commerce.price.should eq 47.25
Faker::Commerce.material.should eq "Rubber"
end
end
7 changes: 7 additions & 0 deletions spec/company_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,11 @@ describe Faker::Company do
it "logo" do
Faker::Company.logo.match(%r{https://pigment.github.io/fake-logos/logos/medium/color/\d+\.png}).should_not eq nil
end

it "should return deterministic results when seeded" do
Faker.seed 123456
Faker::Company.name.should eq "Larson-Altenwerth"
Faker::Company.suffix.should eq "Group"
Faker::Company.logo.should eq "https://pigment.github.io/fake-logos/logos/medium/color/12.png"
end
end
10 changes: 10 additions & 0 deletions spec/hacker_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,14 @@ describe Faker::Hacker do
it "ingverb" do
Faker::Hacker.ingverb.match(/\w+/).should_not eq nil
end

it "should return deterministic results when seeded" do
Faker.seed 123456
Faker::Hacker.say_something_smart.should eq "You can't override the sensor without overriding the primary JBOD transmitter!"
Faker::Hacker.abbreviation.should eq "SCSI"
Faker::Hacker.adjective.should eq "primary"
Faker::Hacker.noun.should eq "pixel"
Faker::Hacker.verb.should eq "transmit"
Faker::Hacker.ingverb.should eq "calculating"
end
end
31 changes: 31 additions & 0 deletions spec/internet_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -166,4 +166,35 @@ describe Faker::Internet do
it "device_token" do
# Faker::Internet.device_token.size.should eq 64
end

it "should return deterministic results when seeded" do
Faker.seed 123456
Faker::Internet.email.should eq "[email protected]"
Faker::Internet.email("Nancy").should eq "[email protected]"
Faker::Internet.free_email.should eq "[email protected]"
Faker::Internet.free_email("Nancy").should eq "[email protected]"
Faker::Internet.safe_email.should eq "[email protected]"
Faker::Internet.safe_email("Nancy").should eq "[email protected]"
Faker::Internet.user_name.should eq "faker.internet"
Faker::Internet.user_name("Nancy").should eq "nancy"
Faker::Internet.user_name("Nancy Johnson", [".", "_", "-"] of ::String).should eq "johnson.nancy"
Faker::Internet.password.should eq "Tb34Ap05U"
Faker::Internet.password(8).should eq "BhI59sBo9"
Faker::Internet.password(10, 20).should eq "9r3b4iL8HeY"
Faker::Internet.password(10, 20, true).should eq "91JpPrF867Z"
Faker::Internet.password(10, 20, true, true).should eq "Pl5q3eOqZsK"
Faker::Internet.domain_name.should eq "ullrichklocko.biz"
Faker::Internet.domain_word.should eq "lockman"
Faker::Internet.domain_suffix.should eq "net"
Faker::Internet.ip_v4_address.should eq "6.70.63.244"
Faker::Internet.ip_v6_address.should eq "8a31:c21c:fb41:eea8:9df:aeab:9f78:5a49"
Faker::Internet.mac_address.should eq "00:4b:14:3d:24:55"
Faker::Internet.mac_address("55:44:33").should eq "55:44:33:36:0e:5d"
Faker::Internet.url.should eq "http://koelpin.biz/internet_faker"
Faker::Internet.url("example.com").should eq "http://example.com/faker_internet"
Faker::Internet.url("example.com", "/foobar.html").should eq "http://example.com/foobar.html"
Faker::Internet.slug.should eq "voluptatem.dicta"
Faker::Internet.slug("foo bar").should eq "foo.bar"
Faker::Internet.slug("foo bar", "-").should eq "foo-bar"
end
end
33 changes: 33 additions & 0 deletions spec/lorem_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require "./spec_helper"

describe Faker::Lorem do
it "should return deterministic results when seeded" do
Faker.seed 123456
Faker::Lorem.word.should eq "voluptatem"
Faker::Lorem.words.should eq ["quos", "recusandae", "sed"]
Faker::Lorem.words(4).should eq ["iusto", "quia", "placeat", "quia"]
Faker::Lorem.words(4, true).should eq ["vis", "ambulo", "vesica", "vivo"]
Faker::Lorem.characters.should eq "xk7jz4c7a0w5ceh9opz68kq3xzdt5d2rtu29ky6jlb1ltxk3xvqkp87o2c7bs070wggzuz78an6t4cg8fejvhskgfe6ry104yc7kam8p91oaf6bqb61tp84q4958om8glep3wjrl9no32fj1eoklww8bzhvzmdkyp1tn51zxpzm8eynd7mbix1rimwrpufnut2a58d76mwrn4epjao7pedef2roosl2simxsvi4lejwzrdojegew2csobpw2lym"
Faker::Lorem.characters(10).should eq "vp5j8u3r1l"
Faker::Lorem.sentence.should eq "Itaque quod aliquam veritatis nemo dolorum sequi."
Faker::Lorem.sentence(3).should eq "Accusantium dolores suscipit praesentium."
Faker::Lorem.sentence(3, true).should eq "Spiculum triumphus necessitatibus appono angulus aut cariosus."
Faker::Lorem.sentence(3, false, 4).should eq "Atque sed perferendis minus."
Faker::Lorem.sentence(3, true, 4).should eq "Cohors traho tamdiu alveus itaque."
Faker::Lorem.sentences.should eq ["Sed ab quia.",
"Consequatur doloremque dolores ratione voluptas esse aut vero.",
"Qui dicta est odit nihil exercitationem nesciunt."]
Faker::Lorem.sentences(1).should eq ["Reiciendis doloremque vero sequi et quia."]
Faker::Lorem.sentences(1, true).should eq ["Concido quisquam cerno vulpes maxime mollitia."]
Faker::Lorem.paragraph.should eq "Maxime magnam vel velit id. Sed cupiditate blanditiis. Cupiditate sit aliquam vero."
Faker::Lorem.paragraph(2).should eq "Nemo laboriosam quod accusamus ab modi excepturi. Eveniet rerum quasi quia culpa. Vero quis aut. A assumenda tenetur."
Faker::Lorem.paragraph(2, true).should eq "Pecunia sopor ars vero subiungo quis urbanus. Demens minus delinquo."
Faker::Lorem.paragraph(2, false, 4).should eq "Mollitia delectus qui et ut quasi. Eligendi aut facilis praesentium ducimus qui. Itaque molestiae laudantium qui omnis veritatis soluta. Quia reiciendis dignissimos saepe architecto. Eum excepturi dolores iusto quisquam."
Faker::Lorem.paragraph(2, true, 4).should eq "Depraedor vitae spectaculum cupio acervus conatus adipisci. Pecus vulgivagus terra aliqua arbitro. Suscipio socius cupiditas arguo cetera colloco trans solitudo. Adimpleo stillicidium eaque ocer placeat adstringo ustulo balbus. Versus viduo videlicet tenus absconditus."
Faker::Lorem.paragraphs.should eq ["Rerum odit ducimus ipsum at sint. Consequatur sed non dolorem. Incidunt quae libero. Enim quam molestiae necessitatibus.",
"Inventore eos dolores asperiores corrupti cupiditate. Illum at molestiae cumque eaque aut. Blanditiis et laudantium neque. Consequatur labore officiis pariatur possimus facilis.",
"Esse fuga cum quisquam tenetur impedit rem repellat. Quia deleniti nulla. Excepturi perferendis dolor accusamus."]
Faker::Lorem.paragraphs(1).should eq ["Rerum unde voluptas sint autem. Fugit tenetur sequi totam esse. Explicabo omnis consequatur inventore autem. Et et praesentium neque quo natus."]
Faker::Lorem.paragraphs(1, true).should eq ["Conitor reiciendis minima viridis temporibus spiritus. Tabula crustulum error titulus et comptus. Coruscus turpis amplitudo combibo alias deludo triginta."]
end
end
13 changes: 13 additions & 0 deletions spec/name_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require "./spec_helper"

describe Faker::Name do
it "should return deterministic results when seeded" do
Faker.seed 123456
Faker::Name.name.should eq "Bernie Altenwerth"
Faker::Name.first_name.should eq "Ron"
Faker::Name.last_name.should eq "Block"
Faker::Name.prefix.should eq "Mrs."
Faker::Name.suffix.should eq "Sr."
Faker::Name.title.should eq "Product Markets Specialist"
end
end
12 changes: 12 additions & 0 deletions spec/number_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,16 @@ describe Faker::Number do
Faker::Number.hexadecimal(4).match(/[0-9a-f]{4}/).should_not eq nil
Faker::Number.hexadecimal(7).match(/[0-9a-f]{7}/).should_not eq nil
end

it "should return deterministic results when seeded" do
Faker.seed 123456
Faker::Number.number(10).should eq "6961710422"
Faker::Number.decimal(2).should eq "82.34"
Faker::Number.decimal(2, 3).should eq "21.217"
Faker::Number.hexadecimal(3).should eq "046"
Faker::Number.between(1, 10).should eq 2
Faker::Number.positive.should eq 3995.8054520295627
Faker::Number.negative.should eq -748.5527873256278
Faker::Number.digit.should eq "2"
end
end
8 changes: 8 additions & 0 deletions spec/phone_number_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
require "./spec_helper"

describe Faker::PhoneNumber do
it "should return deterministic results when seeded" do
Faker.seed 123456
Faker::PhoneNumber.phone_number.should eq "361-710-4228 x23421"
end
end
7 changes: 7 additions & 0 deletions spec/team_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,11 @@ describe Faker::Team do
it "sport" do
# Faker::Team.sport.match(/(\w+){1}/).should_not eq nil
end

it "should return deterministic results when seeded" do
Faker.seed 123456
Faker::Team.creature.should eq "buffalo"
Faker::Team.name.should eq "Washington sorcerors"
Faker::Team.state.should eq "Delaware"
end
end
34 changes: 20 additions & 14 deletions src/faker.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ require "./data.cr"
require "./faker/*"

module Faker
class_getter rng : Random = Random.new

def self.seed(number)
@@rng = Random.new number
end

def self.numerify(number_string)
number_string = number_string.as String
number_string.sub(/#/) { (rand(9) + 1).to_s }.gsub(/#/) { rand(10).to_s }
number_string.sub(/#/) { (@@rng.rand(9) + 1).to_s }.gsub(/#/) { @@rng.rand(10).to_s }
end

def self.letterify(letter_string)
letter_string.gsub(/\?/) { ("A".."Z").to_a.sample }
letter_string.gsub(/\?/) { ("A".."Z").to_a.sample(@@rng) }
end

def self.bothify(string)
Expand All @@ -17,21 +23,21 @@ module Faker

def self.regexify(re)
re = re.source if re.is_a?(Regex)
re.gsub(/^\/?\^?/, "").gsub(/\$?\/?$/, "") # Ditch the anchors
.gsub(/\{(\d+)\}/) { "{#{$1},#{$1}}" }.gsub(/\?/, "{0,1}") # All {2} become {2,2} and ? become {0,1}
.gsub(/(\[[^\]]+\])\{(\d+),(\d+)\}/) { |match| $1 * (Range.new($2.to_i, $3.to_i)).to_a.sample } # [12]{1,2} becomes [12] or [12][12]
.gsub(/(\([^\)]+\))\{(\d+),(\d+)\}/) { |match| $1 * ($2.to_i..$3.to_i).to_a.sample } # (12|34){1,2} becomes (12|34) or (12|34)(12|34)
.gsub(/(\\?.)\{(\d+),(\d+)\}/) { |match| $1 * ($2.to_i..$3.to_i).to_a.sample } # A{1,2} becomes A or AA or \d{3} becomes \d\d\d
.gsub(/\((.*?)\)/) { |match| match.gsub(/[\(\)]/, "").split("|").sample } # (this|that) becomes "this" or "that"
.gsub(/\[([^\]]+)\]/) { |match| match.gsub(/(\w\-\w)/) { |range| ((0...range.size).map { |i| range[i].to_s }).join("").split("-").to_a.sample } } # All A-Z inside of [] become C (or X, or whatever)
.gsub(/\[([^\]]+)\]/) { |match| $1.split("").sample } # All [ABC] become B (or A or C)
.gsub("\\d") { |match| (0..9).to_a.sample }
.gsub("\\w") { |match| (("A".."Z").to_a + (0..9).to_a).sample }
re.gsub(/^\/?\^?/, "").gsub(/\$?\/?$/, "") # Ditch the anchors
.gsub(/\{(\d+)\}/) { "{#{$1},#{$1}}" }.gsub(/\?/, "{0,1}") # All {2} become {2,2} and ? become {0,1}
.gsub(/(\[[^\]]+\])\{(\d+),(\d+)\}/) { |match| $1 * (Range.new($2.to_i, $3.to_i)).to_a.sample(@@rng) } # [12]{1,2} becomes [12] or [12][12]
.gsub(/(\([^\)]+\))\{(\d+),(\d+)\}/) { |match| $1 * ($2.to_i..$3.to_i).to_a.sample(@@rng) } # (12|34){1,2} becomes (12|34) or (12|34)(12|34)
.gsub(/(\\?.)\{(\d+),(\d+)\}/) { |match| $1 * ($2.to_i..$3.to_i).to_a.sample(@@rng) } # A{1,2} becomes A or AA or \d{3} becomes \d\d\d
.gsub(/\((.*?)\)/) { |match| match.gsub(/[\(\)]/, "").split("|").sample(@@rng) } # (this|that) becomes "this" or "that"
.gsub(/\[([^\]]+)\]/) { |match| match.gsub(/(\w\-\w)/) { |range| ((0...range.size).map { |i| range[i].to_s }).join("").split("-").to_a.sample(@@rng) } } # All A-Z inside of [] become C (or X, or whatever)
.gsub(/\[([^\]]+)\]/) { |match| $1.split("").sample(@@rng) } # All [ABC] become B (or A or C)
.gsub("\\d") { |match| (0..9).to_a.sample(@@rng) }
.gsub("\\w") { |match| (("A".."Z").to_a + (0..9).to_a).sample(@@rng) }
end

def self.fetch(data)
data = data.as Array
fetched = data.sample.as String
fetched = data.sample(@@rng).as String
if fetched.match(/^\//) && fetched.match(/\/$/) # A regex
fetched = Faker.regexify(fetched)
end
Expand Down Expand Up @@ -74,6 +80,6 @@ module Faker
# Generates a random value between the interval
def self.rand_in_range(from, to)
from, to = to, from if to < from
Random.new.rand(from..to)
@@rng.rand(from..to)
end
end
12 changes: 6 additions & 6 deletions src/faker/address.cr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module Faker
class Address
def self.zip_code
Faker.numerify(["#####", "#####-####"].sample)
Faker.numerify(["#####", "#####-####"].sample(Faker.rng))
end

{% for data_type in %w(state state_abbr city_suffix city_prefix country street_suffix country_code) %}
Expand All @@ -18,7 +18,7 @@ module Faker
[
->{ [Name.last_name, street_suffix].join(" ") },
->{ [Name.first_name, street_suffix].join(" ") },
].sample.call
].sample(Faker.rng).call
end

def self.street_address
Expand All @@ -29,7 +29,7 @@ module Faker
->{ "##### %s" % street_name },
->{ "##### %s Apt. ###" % street_name },
->{ "##### %s Suite ###" % street_name },
].sample.call)
].sample(Faker.rng).call)
end

def self.secondary_address
Expand All @@ -44,15 +44,15 @@ module Faker
Faker.bothify([
->{ "??# #??" },
->{ "??## #??" },
].sample.call)
].sample(Faker.rng).call)
end

def self.latitude
((rand * 180) - 90).to_s
((Faker.rng.rand * 180) - 90).to_s
end

def self.longitude
((rand * 360) - 180).to_s
((Faker.rng.rand * 360) - 180).to_s
end

def self.time_zone
Expand Down
4 changes: 2 additions & 2 deletions src/faker/commerce.cr
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module Faker

def self.department(max = 3, fixed_amount = false)
num = max if fixed_amount
num ||= 1 + rand(max)
num ||= 1 + Faker.rng.rand(max)

categories = categories(num)

Expand All @@ -28,7 +28,7 @@ module Faker
end

def self.price(range = 0.0..100.0)
(rand(range) * 100).floor/100.0
(Faker.rng.rand(range) * 100).floor/100.0
end

private def self.categories(num)
Expand Down
2 changes: 1 addition & 1 deletion src/faker/company.cr
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ module Faker
end

def self.logo
rand_num = Random.rand(13) + 1
rand_num = Faker.rng.rand(13) + 1
"https://pigment.github.io/fake-logos/logos/medium/color/#{rand_num}.png"
end
end
Expand Down
16 changes: 8 additions & 8 deletions src/faker/hacker.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
module Faker
class Hacker
def self.say_something_smart
phrases.sample
phrases.sample(Faker.rng)
end

{% for data_type in %w(abbreviation adjective noun verb ingverb) %}
Expand All @@ -13,13 +13,13 @@ module Faker

def self.phrases
["If we #{verb} the #{noun}, we can get to the #{abbreviation} #{noun} through the #{adjective} #{abbreviation} #{noun}!",
"We need to #{verb} the #{adjective} #{abbreviation} #{noun}!",
"Try to #{verb} the #{abbreviation} #{noun}, maybe it will #{verb} the #{adjective} #{noun}!",
"You can't #{verb} the #{noun} without #{ingverb} the #{adjective} #{abbreviation} #{noun}!",
"Use the #{adjective} #{abbreviation} #{noun}, then you can #{verb} the #{adjective} #{noun}!",
"The #{abbreviation} #{noun} is down, #{verb} the #{adjective} #{noun} so we can #{verb} the #{abbreviation} #{noun}!",
"#{ingverb} the #{noun} won't do anything, we need to #{verb} the #{adjective} #{abbreviation} #{noun}!",
"I'll #{verb} the #{adjective} #{abbreviation} #{noun}, that should #{noun} the #{abbreviation} #{noun}!",
"We need to #{verb} the #{adjective} #{abbreviation} #{noun}!",
"Try to #{verb} the #{abbreviation} #{noun}, maybe it will #{verb} the #{adjective} #{noun}!",
"You can't #{verb} the #{noun} without #{ingverb} the #{adjective} #{abbreviation} #{noun}!",
"Use the #{adjective} #{abbreviation} #{noun}, then you can #{verb} the #{adjective} #{noun}!",
"The #{abbreviation} #{noun} is down, #{verb} the #{adjective} #{noun} so we can #{verb} the #{abbreviation} #{noun}!",
"#{ingverb} the #{noun} won't do anything, we need to #{verb} the #{adjective} #{abbreviation} #{noun}!",
"I'll #{verb} the #{adjective} #{abbreviation} #{noun}, that should #{noun} the #{abbreviation} #{noun}!",
]
end
end
Expand Down
Loading

0 comments on commit 4176ac1

Please sign in to comment.