นำขั้นตอนแตงกวากลับมาใช้ใหม่


103

ฉันต้องการใช้ขั้นตอนบางอย่างของแตงกวาซ้ำ แต่ดูเหมือนจะหาวิธีที่ถูกต้องไม่ได้

ฉันต้องการเขียนขั้นตอนดังนี้:

Given /^I login with (.*) credentials$/ |type|
  # do stuff with type being one of "invalid" or "valid"
end

แต่มีขั้นตอนอื่นเช่น:

Given /^I login successfully$
  # call "Given I login with valid credentials"
end

ดังนั้นในการทดสอบการพิสูจน์ตัวตนผู้ใช้ฉันสามารถใช้แบบเดิมได้ แต่ที่อื่น ๆ ส่วนใหญ่ฉันสามารถใช้แบบหลังได้และไม่จำเป็นต้องทำรหัสซ้ำ

มีวิธีเรียกขั้นตอนอื่นหรือไม่หรือฉันแค่ใส่ตรรกะในวิธีการช่วยเหลือและเรียกวิธีการดังกล่าวจากแต่ละงาน (โดยทั่วไปคือการแยกวิธีการ refactoring ซึ่งหลังจากอ่านคำถามของฉันทำให้ฉันเชื่อว่านั่นเป็นวิธีที่ดีที่สุดจริงๆ อย่างไรก็ตาม)?


1
ในกรณีที่มีใครสับสนทุกคนที่นี่จะไม่doจำเป็นต้องเริ่มdo...endบล็อกในคำจำกัดความขั้นตอน Ruby ในความเป็นจริงจำเป็น
Shaun Lebron

คำตอบ:


102

อัปเดต : วิธีการที่อธิบายไว้ด้านล่างถูกเลิกใช้แล้ว วิธีที่แนะนำในการเรียกขั้นตอนจากภายในขั้นตอนอื่นจะมีลักษณะดังนี้:

Given /^I login successfully$/
    step "I login with valid credentials" 
end 

วิธีเก่าที่เลิกใช้แล้ว (สำหรับการอ้างอิง):

คุณสามารถเรียกขั้นตอนจากขั้นตอนอื่น ๆ ดังนี้:

Given /^I login successfully$/
  Given "I login with valid credentials"
  Then "I should be logged in"
end

หากสถานการณ์ทั้งหมดภายในฟีเจอร์ต้องการสิ่งนี้ (หรือขั้นตอนอื่น ๆ ) คุณยังสามารถเพิ่มพื้นหลังให้กับแต่ละคุณสมบัติได้โดยทำตามขั้นตอนทั่วไปดังนี้:

Background:
  Given I log in with valid credentials

Scenario: Change my password
  Given I am on the account page

5
ง่ายยิ่งกว่านั้นคือการวางรหัสสีเหลืองเช่นนี้:steps %Q{Given I am logged in}
BrendanDean

1
@BrendanDean เมื่อคำตอบนี้ได้รับการยอมรับstepsวิธีนี้ก็ไม่มีอยู่จริง ดูคำตอบของฉันด้านล่าง
michaeltwofish

โปรดทราบว่าขั้นตอนการทำงานร่วมกันถือเป็นการต่อต้านรูปแบบและควรหลีกเลี่ยง ดูวิกิแตงกวา
Jan Molak

103

โปรดทราบว่าวิธีการเรียกใช้ขั้นตอนภายในขั้นตอนมีการเปลี่ยนแปลงในแตงกวาเวอร์ชันล่าสุดซึ่งคุณจะเห็นว่าคุณได้รับข้อผิดพลาดเช่น "คำเตือน: การใช้ 'Given / When / Then' ในคำจำกัดความของขั้นตอนถูกเลิกใช้แล้วให้ใช้ 'step' เพื่อ เรียกขั้นตอนอื่นแทน: /path/to/step_definitions/foo_steps.rb: 631: ใน `` block in '' ดูวิกิแตงกวาสำหรับรายละเอียด

ความสำคัญของการเปลี่ยนแปลงคือตอนนี้คุณควรใช้stepหรือstepsวิธีการ

When /^I make all my stuff shiny$/
  step "I polish my first thing"
end

When /^I make all my stuff shiny$/
  steps %Q{
    When I polish my first thing
    When I shine my second thing
  }
end

18
สำหรับสิ่งที่คุ้มค่าหลังจากใช้เวลากับแตงกวามากขึ้นฉันขอแนะนำว่าอย่าใช้ขั้นตอนภายในขั้นตอนเลย ปัญหานั้นยากที่จะติดตามและทำให้การบำรุงรักษายากขึ้น ให้ใช้วิธีการช่วยเหลือแทน
michaeltwofish

2
บางทีคุณควรใส่ความคิดเห็นนี้ไว้ในคำตอบของคุณเนื่องจากมีการโหวตสูงมากและยังคงได้รับการโหวต จะช่วยให้ผู้คนสังเกตเห็นข้อมูลนี้
Andrei Botalov

สวัสดี @michaeltwofish ปี 2017 มีการเปลี่ยนแปลงอะไรบ้างไหม ฉันได้รับsyntax error, unexpected tIDENTIFIER, expecting keyword_end stackoverflow.com/questions/43319331/…
ericn

43

การเรียกขั้นตอนจากคำจำกัดความขั้นตอนเป็นแนวทางปฏิบัติที่ไม่ดีและมีข้อเสียดังนี้

  1. หากสถานการณ์จะล้มเหลวและมีการเรียกใช้ขั้นตอนที่ซ้อนกันคุณจะได้รับเฉพาะนิยามขั้นตอนที่เรียกครั้งสุดท้ายในการติดตามสแต็ก อาจจะหายากที่จะเรียกว่า stepdef ครั้งสุดท้าย
  2. บางครั้งการโทรหา stepdef หาและอ่านยากกว่าวิธีการทับทิม
  3. วิธี Ruby ให้พลังมากกว่าการเรียกขั้นตอนจาก step defs

Aslak Hellesøy แนะนำให้แยกการกระทำที่เป็นที่นิยมไปยังWorldแทนที่จะใช้ขั้นตอนซ้ำ มันแยกการกระทำเหล่านั้นไว้ในที่เดียวทำให้ค้นหารหัสนี้ได้ง่ายขึ้น คุณสามารถแยกโค้ดไปยังคลาสหรือโมดูล Ruby ตามปกติได้เช่นกัน

#/support/world_extensions.rb
module KnowsUser
  def login
    visit('/login')
    fill_in('User name', with: user.name)
    fill_in('Password', with: user.password)
    click_button('Log in')
  end

  def user
    @user ||= User.create!(:name => 'Aslak', :password => 'xyz')
  end
end
World(KnowsUser)

#/step_definitions/authentication_steps.rb
When /^I login$/ do
  login
end

Given /^a logged in user$/ do
  login
end

นี่คือการสนทนาที่เป็นประโยชน์ในหัวข้อนี้ในรายการส่งเมล Cucumber - ลิงค์


2
ฉันเชื่อว่าวิธีนี้ดีกว่าการเรียกใช้ฟังก์ชัน step หรือ steps ด้วยเหตุผลเดียวกันกับที่กล่าวมาข้างต้น
pisaruk

2
สิ่งนี้มีประโยชน์อีกอย่าง เมื่อใช้ Idea (หรือ Rubymine) คุณสามารถข้ามไปยังฟังก์ชันนิยามได้อย่างง่ายดาย แต่จะข้ามไปยังขั้นตอนในขั้นตอน% {... } ไม่ได้
สลิปเซ็ต

นอกจากนี้การตั้งค่านี้ยังเป็นไปตามหลักการ DRY
Sorcerer86pt

2
แม้ว่าฉันจะประสบปัญหาในการใช้ขั้นตอนซ้ำ แต่ฉันคิดว่ามันไม่ดี การเข้าสู่ระบบเป็นเพียงผลรวมของขั้นตอนต่างๆ: "เยี่ยมชมบางสิ่ง" "เติมบางสิ่ง" วิธีที่เป็นธรรมชาติจะใช้ขั้นตอนซ้ำแทนที่จะแปลงแต่ละขั้นตอนเป็นการเรียกใช้ฟังก์ชัน IMO ขั้นตอนการโทรภายในขั้นตอนควรได้รับการปรับปรุง
dgmora

9

ดีที่สุดรวมขั้นตอนของคุณเป็น% {} แทนที่จะเป็นเครื่องหมายคำพูด จากนั้นคุณไม่จำเป็นต้องหลีกหนีเครื่องหมายคำพูดคู่ที่คุณต้องใช้บ่อยๆ:

Given /^I login successfully$
  step %{I login with valid credentials}
end

Given /^I login with (.*) credentials$/ |type|
  # do stuff with type being one of "invalid" or "valid"
end

5
นี่ควรเป็นความคิดเห็นแทนคำตอบ
Kelvin

1

ใช้คำหลักซ้ำในไฟล์ฟีเจอร์ซึ่งจะช่วยให้สามารถใช้รหัสซ้ำได้

ไม่แนะนำอย่างยิ่งให้เรียก step def ภายใน step defs

ฉันจะเขียนไฟล์คุณสมบัติของฉันด้วยวิธีนี้

Scenario Outline: To check login functionality
    Given I login with "<username>" and "<password>"
    Then I "<may or may not>" login successfully

Examples:
    |username|password|may or may not|
    |paul    |123$    |may           |
    |dave    |1111    |may not       |

ในนิยามขั้นตอนของฉัน (นี่คือ Java)

@Given(I login with \"([^\"]*)\" and \"([^\"]*)\"$)
public void I_login_with_and(String username, String password){

   //login with username and password

}

@Then(I \"([^\"]*)\" login successfully$)
public void I_login_successully_if(String validity){

    if(validity.equals("may")){
        //assert for valid login
    }
    else
    if(validity.equals("may not")){
        //assert for invalid login
    }
}

ด้วยวิธีนี้มีความสามารถในการใช้โค้ดซ้ำได้มาก Given and Then เดียวกันของคุณจะจัดการทั้งสถานการณ์ที่ถูกต้องและไม่ถูกต้อง ในขณะเดียวกันไฟล์ฟีเจอร์ของคุณก็มีประโยชน์ต่อผู้อ่าน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.