Coverage 모듈
Coverage 모듈
Coverage는 Ruby의 커버리지 측정 기능을 제공해요. 이 기능은 실험적이라 앞으로 API가 바뀔 수 있어요. 지켜야 할 제약 하나가 있는데, 현재는 프로세스 전역 커버리지 측정만 지원해요. 스레드 단위 커버리지는 측정할 수 없어요.
출처: Ruby 4.0 API
본문
Coverage는 Ruby의 커버리지 측정 기능을 제공해요. 실험적 기능이라 API는 앞으로 바뀔 수 있어요.
주의: 현재는 프로세스 전역 커버리지 측정만 지원해요. 스레드 단위 커버리지는 측정할 수 없어요.
사용법
require "coverage"Coverage.start실행- Ruby 소스 파일 require 또는 load
Coverage.result는 파일명을 키로, 커버리지 배열을 값으로 하는 해시를 돌려줘요. 커버리지 배열은 줄마다 그 줄이 인터프리터에 의해 실행된 횟수를 담아요.nil값은 그 줄(예:else와end같은 줄)에 대해 커버리지가 비활성화됐다는 뜻이에요.
예시
[foo.rb]
s = 0
10.times do |x|
s += x
end
if s == 45
p :ok
else
p :ng
end
[EOF]
require "coverage"
Coverage.start
require "foo.rb"
p Coverage.result #=> {"foo.rb"=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil]}
Lines 커버리지
커버리지 시작 시 모드를 명시하지 않으면 lines 커버리지가 실행돼요. 각 줄이 실행된 횟수를 보고해요.
require "coverage"
Coverage.start(lines: true)
require "foo.rb"
p Coverage.result #=> {"foo.rb"=>{:lines=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil]}}
lines 커버리지 결과의 값은 각 줄이 실행된 횟수를 담은 배열이에요. 이 배열에서 순서가 중요해요. 예를 들어 index 0의 첫 항목은 커버리지 측정 동안 이 파일의 1번째 줄이 실행된 횟수(이 예시에서는 한 번)를 보고해요.
nil 값은 그 줄(예: else와 end)에 대해 커버리지가 비활성화됐다는 뜻이에요.
Oneshot Lines 커버리지
Oneshot lines 커버리지는 커버리지가 실행되는 동안 실행된 줄을 추적해서 보고해요. 몇 번 실행됐는지는 보고하지 않고, 실행됐는지 여부만 보고해요.
require "coverage"
Coverage.start(oneshot_lines: true)
require "foo.rb"
p Coverage.result #=> {"foo.rb"=>{:oneshot_lines=>[1, 2, 3, 6, 7]}}
oneshot lines 커버리지 결과의 값은 실행된 줄 번호를 담은 배열이에요.
Branches 커버리지
Branches 커버리지는 각 조건문 안의 각 분기가 몇 번 실행됐는지 보고해요.
require "coverage"
Coverage.start(branches: true)
require "foo.rb"
p Coverage.result #=> {"foo.rb"=>{:branches=>{[:if, 0, 6, 0, 10, 3]=>{[:then, 1, 7, 2, 7, 7]=>1, [:else, 2, 9, 2, 9, 7]=>0}}}}
branches 해시의 각 항목은 조건문 하나예요. 그 값은 또 다른 해시로, 각 항목이 그 조건문 안의 분기를 나타내요. 값은 메서드가 실행된 횟수이고, 키는 분기를 식별하는 정보예요.
각 분기나 조건문을 식별하는 키를 이루는 정보는 왼쪽부터 다음과 같아요:
- 분기 또는 조건문의 타입 라벨.
- 고유 식별자.
- 파일에서 나타나는 시작 줄 번호.
- 파일에서 나타나는 시작 컬럼 번호.
- 파일에서 나타나는 끝 줄 번호.
- 파일에서 나타나는 끝 컬럼 번호.
Methods 커버리지
Methods 커버리지는 각 메서드가 실행된 횟수를 보고해요.
[foo_method.rb]
class Greeter
def greet
"welcome!"
end
end
def hello
"Hi"
end
hello()
Greeter.new.greet()
[EOF]
require "coverage"
Coverage.start(methods: true)
require "foo_method.rb"
p Coverage.result #=> {"foo_method.rb"=>{:methods=>{[Object, :hello, 7, 0, 9, 3]=>1, [Greeter, :greet, 2, 2, 4, 5]=>1}}}
methods 해시의 각 항목은 메서드 하나를 나타내요. 값은 메서드가 실행된 횟수이고, 키는 메서드를 식별하는 정보예요.
메서드를 식별하는 키를 이루는 정보는 왼쪽부터 다음과 같아요:
- 클래스.
- 메서드 이름.
- 파일에서 메서드가 나타나는 시작 줄 번호.
- 시작 컬럼 번호.
- 끝 줄 번호.
- 끝 컬럼 번호.
모든 커버리지 모드
이 단축키로 모든 커버리지 모드를 동시에 실행할 수도 있어요. 모든 커버리지 모드를 실행한다고 lines와 oneshot lines를 둘 다 실행하는 건 아니에요. 그 둘은 동시에 실행할 수 없거든요. 이 경우 lines 커버리지가 실행되는데, 여전히 줄이 실행됐는지를 알아내는 데 쓸 수 있기 때문이에요.
require "coverage"
Coverage.start(:all)
require "foo.rb"
p Coverage.result #=> {"foo.rb"=>{:lines=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil], :branches=>{[:if, 0, 6, 0, 10, 3]=>{[:then, 1, 7, 2, 7, 7]=>1, [:else, 2, 9, 2, 9, 7]=>0}}, :methods=>{}}}
Class Methods
line_stub(file) → array
주어진 소스 코드에서 line 커버리지의 "스텁(stub)"을 만드는 간단한 헬퍼 함수예요.
# File ext/coverage/lib/coverage.rb, line 9
def self.line_stub(file)
lines = File.foreach(file).map { nil }
iseqs = [RubyVM::InstructionSequence.compile_file(file, coverage_enabled: false)]
until iseqs.empty?
iseq = iseqs.pop
iseq.trace_points.each {|n, type| lines[n - 1] = 0 if type == :line }
iseq.each_child {|child| iseqs << child }
end
lines
end
peek_result → hash
파일명을 키로, 커버리지 배열을 값으로 하는 해시를 돌려줘요. Coverage.result(stop: false, clear: false)와 같아요.
{
"file.rb" => [1, 2, nil],
...
}
result(stop: true, clear: true) → hash
파일명을 키로, 커버리지 배열을 값으로 하는 해시를 돌려줘요. clear가 true면 카운터를 0으로 지워요. stop이 true면 커버리지 측정을 비활성화해요.
resume → nil
커버리지 측정을 시작하거나 재개해요.
주의: 현재는 프로세스 전역 커버리지 측정만 지원해요. 스레드 단위 커버리지는 측정할 수 없어요. 프로세스에 여러 스레드가 있다면 Coverage.resume/suspend로 제한된 코드 블록에서만 실행되는 커버리지를 포착하려 할 때, 잘못된 결과가 나올 수 있어요.
running? → bool
커버리지 통계가 현재 수집 중이면(Coverage.start 호출 후 Coverage.result 호출 전) true를 돌려줘요.
setup → nil
setup(:all) → nil
setup(lines: bool, branches: bool, methods: bool, eval: bool) → nil
setup(oneshot_lines: true) → nil
커버리지 측정을 설정해요.
이 메서드는 측정 자체를 시작하지 않는다는 점에 주의하세요. 측정을 시작하려면 Coverage.resume을 사용해요.
Coverage.start로 설정과 시작을 함께 할 수도 있어요.
start → nil
start(:all) → nil
start(lines: bool, branches: bool, methods: bool, eval: bool) → nil
start(oneshot_lines: true) → nil
커버리지 측정을 활성화해요. 자세한 내용은 Coverage 클래스 문서를 보세요. Coverage.setup 과 Coverage.resume 을 합친 것과 같아요.
state → :idle, :suspended, :running
커버리지 측정의 상태를 돌려줘요.
supported?(mode) → true or false
주어진 모드에 대해 커버리지 측정이 지원되면 true를 돌려줘요.
모드는 다음 심볼 중 하나여야 해요: :lines, :oneshot_lines, :branches, :methods, :eval.
예시:
Coverage.supported?(:lines) #=> true
Coverage.supported?(:all) #=> false
suspend → nil
커버리지 측정을 일시 중단해요. Coverage.resume으로 측정을 다시 시작할 수 있어요.