Ruby minitest test output ของเมธอดที่ต้องการอินพุตจากผู้ใช้

แก้ไขแล้ว


คำถามที่ 1: ฉันต้องการเขียนแบบทดสอบสำหรับ file_choice_reader ในชั้นเรียนต่อไปนี้

คลาสจะพิมพ์รายการไฟล์บางประเภทไปยังบรรทัดคำสั่งและให้ผู้ใช้เลือกหนึ่งไฟล์โดยพิมพ์หมายเลขดัชนี

class File_chooser

  #shortened for readability

  def file_choice_suggester
    file_list = file_list_generator
    if file_list.count > 0
      file_list.each_with_index do |file, index|
        puts index.to_s + ' ' + file
      end
    else 
      puts 'Neither .fcv nor .tmpl nor .ipa nor .apf files in directory.'  
    end
    file_list
  end

  def file_choice_reader
    unless File.exists? 'Cookie.txt'
      file_list = file_choice_suggester
      puts 'Choose file by typing index number!'
      chosen_file = STDIN.gets.chomp
      if /[^0-9]/.match(chosen_file) || chosen_file.to_i >= file_list.count
        abort ('No valid index number.')
      else 
        chosen_file = chosen_file.to_i
      end
      cookie_writer(  file_list[chosen_file].to_s )
      system 'cls'
      puts 'You chose file: ' + file_list[chosen_file].to_s
      path_and_file = file_list[chosen_file].to_s
    else
      self.hints_hash = hints_hash.merge( 'cookie_del' => '* Change file by typing command: del Cookie.txt *' )
      pre_chosen_file = File.read('Cookie.txt')
      path_and_file = pre_chosen_file.chomp.to_s
    end
    path_and_file
  end

end

การทดสอบของฉันมีลักษณะเช่นนี้ (ฉันได้รับแจ้งให้พิมพ์หมายเลขดัชนี แต่ก็ยังแจ้งว่าผลลัพธ์คือ ""):

class TestFile_chooser < MiniTest::Unit::TestCase 
  def setup
    @file_chooser = File_chooser.new
  end

  def test_file_choice_reader_produces_confirmation_output
    assert_output( /You chose file/ ) { @file_chooser.file_choice_reader }
  end 
end

ผลลัพธ์ของ file_choice_reader จะเป็น "" เสมอ ฉันจะเพิ่มลำดับการรับอินพุตของผู้ใช้และ /then/ การวัดเอาต์พุตได้อย่างไร

คำถามที่ 2: นี่เป็นคำถามสั้นๆ คลาสการทดสอบเดียวกันกับข้างต้นก็ประกอบด้วย

  def test_file_choice_suggester_produces_output
    assert_output( /apf|fcv|tmpl|ipa/ ) {  @file_chooser.file_choice_suggester }
  end 

การทดสอบนี้ผ่าน แต่มันทิ้งฉันไว้กับ "การวิ่ง 1 ครั้งการยืนยัน 2 ครั้ง" นั่นทำให้ฉันงง การทดสอบ 1 ครั้งในการรัน 1 ครั้งจะสร้างการยืนยัน 2 (??) ได้อย่างไร

ฉันยินดีเป็นอย่างยิ่งที่ได้รับความช่วยเหลือ การอภิปรายเล็กๆ น้อยๆ บนอินเทอร์เน็ตดูเหมือนจะไม่ครอบคลุมสิ่งเหล่านี้ บางทีมันอาจจะเป็นพื้นฐานเกินไป?

(ฉันรู้สึกขอบคุณสำหรับความคิดเห็นอื่น ๆ ทั้งหมดเกี่ยวกับรหัสในความคิดเห็นเช่นกัน ขอบคุณที่ช่วยเหลือ)


อัปเดต (คำถามที่ 1)

ด้วยความช่วยเหลือจากการตอบกลับด้านล่าง การทดสอบเวอร์ชันใหม่ล่าสุดของฉันโดยใช้ตัวอย่างใน http://www.ruby-doc.org/core-2.1.5/Module.html

@file_chooser.instance_eval do 
  self.create_method( :puts ) {|arg| printed = arg} 
end

การทดสอบดำเนินไปโดยไม่มีข้อผิดพลาด ... แต่ ... ยังคงบอกฉันว่า: "การปฏิเสธล้มเหลว ไม่มีข้อความให้"

ขอบคุณสำหรับความช่วยเหลือจนถึงตอนนี้! ขอขอบคุณสำหรับคำแนะนำทั้งหมดเกี่ยวกับวิธีการคิดออก

[การเพิ่มรหัสที่นี่อ่านยากในความคิดเห็น]


อัปเดต 2 (คำถามที่ 1)

ฉันทำตามคำแนะนำสำหรับคำถามอื่นเพื่อกำหนดให้อัญมณีน้อยที่สุดอย่างชัดเจน ฉันวางสิ่งนี้ไว้เหนือโค้ด testfile ของฉัน:

require 'rubygems'
gem 'minitest'
require 'minitest/autorun'
require_relative 'falcon'

(หากซ้ำซ้อนกรุณาแจ้งด้วยนะครับ)

รหัสทดสอบต่อไปนี้ไม่ก่อให้เกิดข้อผิดพลาดหรือความล้มเหลวอีกต่อไป:

  def test_file_choice_suggester_produces_output
    assert_output( /apf|fcv|tmpl|ipa/ ) {  @file_chooser.file_choice_suggester }
  end 

ขอขอบคุณทุกท่านสำหรับความช่วยเหลือของคุณ!


person enahel    schedule 11.11.2014    source แหล่งที่มา
comment
#2 อาจเกี่ยวข้องกับวิธี assert_output ซึ่งมีการยืนยันหลายครั้ง หรือถ้าคุณมีการทดสอบทั้งสองนี้ในไฟล์เดียวกัน   -  person Josh Bodah    schedule 12.11.2014
comment
ในส่วนของสไตล์ ฉันขอแนะนำคู่มือสไตล์ของ GitHub: github.com/styleguide/ruby   -  person Josh Bodah    schedule 12.11.2014
comment
# 1 ไม่แน่ใจว่าคำถามคืออะไร แต่ควรแยกแยะอินพุตของผู้ใช้หรือส่งผ่านอินพุตสตรีมเป็นอาร์กิวเมนต์หรืออะไรบางอย่าง   -  person Josh Bodah    schedule 12.11.2014
comment
ขอบคุณ! คำถามคือ จะเขียนการทดสอบเพื่อให้แน่ใจว่าผู้ใช้ของฉันได้รับข้อความยืนยันได้อย่างไร เอาต์พุตไม่ใช่เอาต์พุตโดยตรงของเมธอด แต่จะปรากฏหลังจากที่ผู้ใช้ป้อนข้อมูลไปยัง sdtin เท่านั้น ขณะนี้การทดสอบบอกฉันว่าวิธีการส่งออกสตริงว่าง นี่ไม่ใช่กรณีหลังจากที่ผู้ใช้ป้อนข้อมูล ฉันต้องเขียนแบบทดสอบอย่างไร? (ฉันหวังว่านี่จะชัดเจนกว่านี้)   -  person enahel    schedule 12.11.2014


คำตอบ (1)


สำหรับ #1:

วิธีหนึ่งอาจเป็นการแยกอ็อบเจ็กต์ IO ที่การทดสอบของคุณใช้โดยการแทนที่วิธี puts อีกประการหนึ่งคือการปรับโครงสร้างการออกแบบของคุณใหม่เพื่อให้วิธีการของคุณมีขนาดเล็กลงและทดสอบได้ง่ายขึ้น

การแทนที่ puts จะเป็นดังนี้:

ในการทดสอบของคุณ:

@file_chooser = File_chooser.new
printed = nil
@file_chooser.instance_eval do
  # Open up the instance and stub out the puts method to save to a local variable
  define_method :puts, Proc.new {|arg| printed = arg}
end
# Run code
refute printed.nil?

หรือคุณสามารถเรียกใช้ความคาดหวังบนวัตถุ $STDOUT เพื่อให้แน่ใจว่าได้รับการเรียกที่ถูกต้อง (ดู Mocha สำหรับ Ruby)

person Josh Bodah    schedule 12.11.2014
comment
ขอบคุณ! น่าเสียดายที่สิ่งนี้ใช้ไม่ได้สำหรับฉัน ข้อความแสดงข้อผิดพลาดคือ:falcon_test.rb:90: ข้อผิดพลาดทางไวยากรณ์ ไม่คาดคิด '{' คาดหวัง keyword_enddefine_method, :puts {|arg| พิมพ์ = arg} ^ falcon_test.rb:90: ข้อผิดพลาดทางไวยากรณ์, ไม่คาดคิด '}', คาดหวัง keyword_end falcon_test.rb:116: ข้อผิดพลาดทางไวยากรณ์, $end ที่ไม่คาดคิด, คาดหวัง keyword_end - person enahel; 13.11.2014
comment
ฉันใส่รหัสลงใน def test .... end ไม่แน่ใจว่าฉันทำอะไรผิด ขอบคุณที่ตอบกลับ - person enahel; 13.11.2014
comment
ขออภัย ฉันผสมไวยากรณ์ ลองตอนนี้ - person Josh Bodah; 14.11.2014
comment
ขอบคุณ! หลังจากอ่านเกี่ยวกับวิธีการกำหนดความเป็นส่วนตัวและแฮ็คซ้ำแล้วซ้ำอีกในหน้านี้ ruby- doc.org/core-2.1.5/Module.html การทดสอบดำเนินไปโดยไม่มีข้อผิดพลาด: @file_chooser.instance_eval do self.create_method( :puts ) {|arg| print = arg} end ... แต่ ... มันยังคงบอกฉันว่าผลลัพธ์ของฉันคือ: In stdout คาดว่า /apf|fcv|tmpl|ipa/ จะตรงกัน ขอบคุณจนถึงตอนนี้ ฉันได้เรียนรู้บางสิ่งบางอย่างอย่างแน่นอน ขอบคุณสำหรับคำแนะนำทั้งหมดว่าจะคิดออกอย่างไร! - person enahel; 15.11.2014
comment
ขออภัย ผสมข้อความแสดงข้อผิดพลาด ข้อความคือ: การหักล้างที่ล้มเหลว ไม่มีข้อความให้ - person enahel; 15.11.2014
comment
ด้านบนฉันได้เพิ่มโค้ดที่ใช้งานได้แล้ว ดูเหมือนว่าปัญหาของฉันเกี่ยวข้องกับการไม่เรียกอัญมณีที่เล็กที่สุดอย่างชัดเจน ขอบคุณสำหรับความช่วยเหลือของคุณ. - person enahel; 01.12.2014