Can't generate more unique values for Sham.last_name

121 views
Skip to first unread message

dinshaw

unread,
Nov 17, 2009, 10:54:06 AM11/17/09
to Machinist Users
Hi All,
I just ran into a bunch of failing specs with this error:
"Can't generate more unique values for Sham.last_name"

I was looking at the code in sham.rb and found this in the initializer
block
40: generate_values(12)

Questions are:
Does it seem like this number might be the cause of my error?
Is this intentionally hard coded?
Is there a reason why it is 12?

Pete Yandell

unread,
Nov 17, 2009, 4:38:35 PM11/17/09
to machini...@googlegroups.com
2009/11/18 dinshaw <gob...@gmail.com>:
> I just ran into a bunch of failing specs with this error:
> "Can't generate more unique values for Sham.last_name"

That error means that Sham is calling your sham definition and getting
the same value back from it repeatedly.

Can you post your sham definition?

> I was looking at the code in sham.rb and found this in the initializer
> block
> 40:     generate_values(12)

That just sets the initial number of generated values to cache. If you
use all of them, Sham will generate more.

- Pete

nruth

unread,
Dec 2, 2009, 3:48:28 PM12/2/09
to Machinist Users
To my understanding, regular shams (in the Sham.define block) must
produce unique values, if there are duplicates it will raise this
error. Pete may want to correct me on that as he knows best :)

If you want repeated values to be allowed try defining them
with :unique => false

e.g:
Sham.contemporary_year(:unique => false) { "#{1950 + rand(100)}" }

As last names are not unique to individuals, this may be the behaviour
you're after?

Regards

Nick

Pete Yandell

unread,
Dec 2, 2009, 4:51:06 PM12/2/09
to Machinist Users
Yep, Sham will discard any values that it's already seen in the random
sequence.

It initially tries to cache 12 values, but dumps any duplicates so you
may end up with less.

When you request more values than it has cached, it tries to double
the number in the cache, again discarding duplicates.

If, when it's doing the doubling, it gets no new unique values from
the sham definition, it throws the "Can't generate more unique values"
exception.

Make sense?

- Pete

dinshaw

unread,
Dec 4, 2009, 10:07:57 AM12/4/09
to Machinist Users
Hi All,
Thanks for you replies, I didn't realize I wasn't getting the emails
until now.

Can you all think of any reason why it wouldn't get any more unique
values when trying to double? Could this be a Faker problem? I am
going to revisit the code and see if my set up or specs could be doing
anything but I am not sure what to look for really.

We have a lot of specs running (big app), shear volume shouldn't be an
issue, I assume.

So my blueprint is:
User.blueprint do
first_name { Sham.first_name }
last_name { Sham.last_name }
email_address { Sham.email }
password 'password'
kind 'normal'
suspended false
profile_complete true
gender "male"
end

My Sham block is:
Sham.define do
first_name { Faker::Name.first_name }
last_name { Faker::Name.last_name }
name { Faker::Name.name }
email { Faker::Internet.email }
title { Faker::Lorem.sentence }
sentence { Faker::Lorem.sentence }
phrase { Faker::Lorem.sentence }
body { Faker::Lorem.paragraphs(3).join("\n\n") }
description { Faker::Lorem.paragraphs(3).join("\n\n") }
blurb { Faker::Lorem.paragraphs(1) }
company { Faker::Company.name }
domain { Faker::Internet.domain_name }
catch_phrase { Faker::Company.catch_phrase }
active_merchant_response_codes {['1','2','3','4'].rand}

document do
file = Tempfile.new('the attached document')
1.upto(50) do
num = rand(50) # random number generation in ruby
file.print(num,"\n") # print number and newline to the file
end
file
end
end


dinshaw

unread,
Dec 4, 2009, 10:41:05 AM12/4/09
to Machinist Users

The errors only happen in full spec runs (rake spec).
If I run the files individually (or through textmate), they all pass.

dinshaw

unread,
Dec 4, 2009, 11:44:33 AM12/4/09
to Machinist Users
Nick, you were correct about not needing unique last names.
That fixed the problem. I can also be fixed by subbing a random string
generator in to Sham.last_name (instead of using
Faker::Name.last_name).

However, I still don't get what exactly is going on, but with a 20 min
spec run being the only way to reproduce, I don't think I will
investigating until it bites me again.

Thanks Pete, for Machinist, it makes life worth testing.

Mitch Saltykov

unread,
Dec 4, 2009, 12:02:46 PM12/4/09
to machini...@googlegroups.com
Looking  at the Faker docs, http://faker.rubyforge.org/rdoc/classes/Faker/Name.html#M000006 shows that Faker::Name.last_name is just

%w(Abbott Abernathy Abshire ... Ziemann Zieme Zulauf).rand
http://faker.rubyforge.org/rdoc/classes/Faker/Name.src/M000006.html

The list of names has just 474 members, so... you must have enough tests in your full Spec run to exhaust the list.
I ran in to something similar when I had a Sham method to generate integer percent values, and at some point wound up with over 101 calls to it -- there just weren't any more integers from 0 to 100 to return! :unique => false was the right solution there, and seems fitting for your case, too.

Pete Yandell

unread,
Dec 5, 2009, 2:56:14 AM12/5/09
to machini...@googlegroups.com
The sham sequence resets for each test, assuming you put the "setup {
Sham.reset }" in your test_helper.rb. That means it only needs to
generate as many Sham values as your largest test needs.

It would be a really bad thing if Sham gave you different data each
time you ran a test depending on the order in which the tests were
run!

You shouldn't have problems with using Faker::Name.last_name in a sham
definition unless you generate an awful lot of objects in a test.

- Pete
Reply all
Reply to author
Forward
0 new messages