2016-11-21 66 views
0

假設我要運行一個測試,並創造了許多Student秒。每個學生都屬於一所學校。學校名稱由法克爾寶石給出,但是有他們的數量有限,學生被關聯到這些學校。FactoryGirl工廠可以重用現有的模型作爲協會

我可以使用FactoryGirl的方式,讓我重新使用現有的學校?即。新FactoryGirl.create(:student)被分配到

  • 一所新學校還沒有僞造=>學校僞造與FactoryGirl.create(:school)
  • 或已經存在的僞造學校=>學校已經是僞造的,並從DB
  • 剛檢索

class Student 
    belongs_to :school, class_name: 'SchoolSociety' 
end 

class School 
    has_many :students 
    field :name 
end 

我相信這裏沒什麼關係,但我使用的是Mongoid。我的工廠會是什麼樣子

FactoryGirl.define do 
    factory :student, class: Student do 
    association(:school, factory: :school) 
    end 
    factory :school, class: School do 
    name { Faker::University.name } 
    end 
end 

一個解決方案是使用School.where(name: Faker::University.name),但我會失去FactoryGirls工廠的所有靈活性... 任何更好的解決方法嗎?

的情況下運行黃瓜測試與很多學生

編輯:

我的實際黃瓜情況下測試了增加根據數學公式涉及到當前的時間和(在已註冊的註冊用戶數的大獎學校)。我在做東西的

Scenario Outline: Jackpot increases with registrations and time 
    Given the current date is <date> 
    And <count> students have registered for the special event 
    When I am on the special event page 
    Then I should see "<jackpot> €" 

    Examples: 
    | date | count | jackpot | 
    | 2016/11/24 15:00:00 | 5 | 4 9 5 , 3 0 | 
    | 2016/11/30 15:00:00 | 10 | 4 9 7 , 6 0 | 
    | 2016/12/10 15:00:00 | 20 | 5 0 2 , 2 0 | 
    | 2016/12/10 15:00:00 | 150 | 6 5 2 , 2 0 | 

現在喜歡,那些<count> students have registered for the special event必須是屬於一個現有的學校(這意味着,在登記過程中的學生,他們必須與學校的電子郵件,其域名存在註冊/可映射在我們的數據庫一School

回答

0

使用黃瓜時,而不是讓工廠規則,你應該是具體的,精確的關於你的吉文斯決定創建什麼。所以,如果你想創建幾個學生在同一所學校我會

Given there is a school with several students

如果你想有幾所學校的學生

Given there are several schools with students

如果你想有一個學生即參加一個以上的學校

Given there is a student enrolled in two schools

很明顯,你可以在這裏通過做這樣的事情

  1. 命名的學校創造各種的創造交易
  2. 命名學生
  3. 不同數量

當你執行這些步驟,尤其是當你開始,它傾向於把所有的代碼在這一步中完成工作。抵制這種情況,而是在步驟中撥打電話並使呼叫與步驟說明相匹配。例如

Given 'there is a school with several students' do 
    @school = create_school 
    @students = [] 
    several.times do 
    @students << create_student school: school 
    end 
end 

該步驟使用兩種方法create_schoolcreate_student。您將一個輔助模塊

module SchoolsStepHelper 
    def create_school 
    ... 

    def create_student(school: ...) 
    ... 
end 
World SchoolsStepHelper 

現在,你如何建立你的學生,你可以得到準確的定義這些,當你遇到新的東西例如一名學生在兩所學校註冊,您可以添加/修改您的方法以獲得此額外功能,例如您可以添加

def enroll_student(student: school:) 
    ... 

,使我們可以做

Given 'there is a student enrolled in two schools' do 
    @student = create_student 
    @school_1 = create_school 
    @school_2 = create_schoo 
    enroll_student(student: @student, school: @school_1) 
    enroll_student(student: @student, school: @school_1) 
end 

但是現在我們仍然在我們的步驟定義太多的代碼,所以我們需要重構。在這裏,我們有幾個選擇

  1. 打破這個複合步驟到更簡單的步驟,使學生和學校已經存在,例如,

    假設有一所學校哈佛 而且還有一個學校耶魯 而且還有一個學生弗雷德 弗雷德在耶魯大學和哈佛大學就讀。

你會做這樣的事情的方式,使您的方案更具描述性,開發登記功能特別是當

  • 提取更高層次方法

    鑑於「有就讀於兩所學校學生」做 @student = create_dual_enrolled_student 結束

  • 您選擇了哪種方法,您將重複使用我們在此答案開頭創建的簡單方法。

    現在你的關於工廠的問題基本上是一個實現細節,關於你如何創建事物。它應該是可能的

    1. 實施一個解決方案,需要很少或根本不瞭解工廠瞭解發生了什麼。 (只是非常簡單的工廠電話在你的方法)

    2. 實施甚至不使用工廠的解決方案(這是我贊成的方法,但這是一個完整的其他故事)。

    最後,如果你採用這種方法,您的所有步驟定義爲簡單的調用來實現的話,那不一樣,如果你有很多的相似的步驟定義例如關係

    Given there is a student 
    Given Fred is a student 
    Given there is a student Fred 
    Given there is a student Sue 
    

    您可以對這些每一個步驟定義而不會產生重複,因爲打電話是不是重複和額外步驟的成本只是有關執行的簡單和需要沒有參數或平衡regexs。

    Given 'there is a student' do 
        create_student 
    end 
    Given 'Fred is a student' do 
        create_student name: 'Fred' 
    end 
    Given there is a student Fred do 
        create_student name: Fred 
    end 
    Given 'there is a student Sue' do 
        create_student name: 'Sue' 
    end 
    

    這是一個很長的答案,我希望它的用處。

    +0

    感謝您的回答,我編輯我的帖子以添加我的具體案例。大量用戶生成事件頭獎。 –

    +0

    我會寫一個後臺步驟來解決你目前的情況'鑑於有數百名學生'。由於你的場景只對註冊特殊事件感興趣,所以學校無關緊要。爲了快速做到這一點,我可能會使用數據庫轉儲,Factory Girl在執行此操作時速度非常慢。 – diabolist

    +0

    我進一步細化了我的問題以刪除不相關的東西,但學校在這裏很重要(實際上是提出問題的唯一原因)。只有在學校註冊時,學生纔可以註冊。但是,是的,我想轉儲可能是去這裏的最佳途徑... –