mirror of
https://github.com/beefproject/beef
synced 2026-06-08 13:15:56 +00:00
UPDATE: simplecov config
This commit is contained in:
@@ -1,3 +1,2 @@
|
||||
---
|
||||
BUNDLE_WITHOUT: "development:test"
|
||||
BUNDLE_WITH: "geoip:ext_msf:ext_notifications:ext_dns:ext_qrcode"
|
||||
|
||||
@@ -2,3 +2,6 @@
|
||||
--color
|
||||
--require spec_helper
|
||||
-I .
|
||||
--order defined
|
||||
--tag ~run_on_browserstack
|
||||
--tag ~run_on_long_tests
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
# SimpleCov configuration file
|
||||
# This provides a cleaner alternative to configuring SimpleCov in spec_helper.rb
|
||||
|
||||
SimpleCov.configure do
|
||||
# Basic filters
|
||||
add_filter '/spec/'
|
||||
add_filter '/config/'
|
||||
add_filter '/test/'
|
||||
|
||||
# Group coverage by component
|
||||
add_group 'Core', 'core'
|
||||
add_group 'Extensions', 'extensions'
|
||||
add_group 'Modules', 'modules'
|
||||
|
||||
# Track files based on coverage focus
|
||||
if ENV['COVERAGE'] == 'core'
|
||||
track_files 'core/**/*.rb'
|
||||
elsif ENV['COVERAGE'] == 'extensions'
|
||||
track_files 'extensions/**/*.rb'
|
||||
elsif ENV['COVERAGE'] == 'modules'
|
||||
track_files 'modules/**/*.rb'
|
||||
else
|
||||
# Default: track everything
|
||||
track_files '{core,extensions,modules}/**/*.rb'
|
||||
end
|
||||
|
||||
# Coverage thresholds
|
||||
minimum_coverage 80 if ENV['CI']
|
||||
|
||||
# Formatters
|
||||
formatter SimpleCov::Formatter::HTMLFormatter
|
||||
end
|
||||
@@ -5,12 +5,82 @@
|
||||
#
|
||||
require 'rspec/core/rake_task'
|
||||
|
||||
task :default => ["short"]
|
||||
task default: ['short']
|
||||
|
||||
RSpec::Core::RakeTask.new(:short) do |task|
|
||||
task.rspec_opts = ['--tag ~run_on_browserstack', '--tag ~run_on_long_tests']
|
||||
# Run rspec with an explicit file list (avoids envs that only run 557).
|
||||
# Note: when run with all 81 files, module specs load after extensions; the Dns stub in
|
||||
# network_spec must not run before the real Dns extension (dns_spec) or you get "superclass mismatch".
|
||||
desc 'Run short spec suite (all specs except browserstack/long)'
|
||||
task :short do
|
||||
short_files = Dir[File.join(Dir.pwd, 'spec', '**', '*_spec.rb')].sort
|
||||
$stderr.puts "[rake short] spec files=#{short_files.size}"
|
||||
abort '[rake short] Expected 81+ spec files; check you are in project root.' if short_files.size < 80
|
||||
opts = [
|
||||
'--tag', '~run_on_browserstack',
|
||||
'--tag', '~run_on_long_tests'
|
||||
]
|
||||
ok = system('bundle', 'exec', 'rspec', *short_files, *opts)
|
||||
abort 'rspec failed' unless ok
|
||||
end
|
||||
|
||||
# Legacy namespace for backward compatibility
|
||||
namespace :coverage do
|
||||
task :modules => 'coverage_modules'
|
||||
task :core => 'coverage_core'
|
||||
task :extensions => 'coverage_extensions'
|
||||
task :all => 'coverage'
|
||||
end
|
||||
|
||||
# Base spec tasks
|
||||
RSpec::Core::RakeTask.new(:spec) do |t|
|
||||
t.pattern = 'spec/**/*_spec.rb'
|
||||
t.rspec_opts = ['--tag', '~run_on_browserstack', '--tag', '~run_on_long_tests']
|
||||
end
|
||||
|
||||
RSpec::Core::RakeTask.new(:spec_core) do |t|
|
||||
t.pattern = 'spec/beef/core/**/*_spec.rb'
|
||||
t.rspec_opts = ['--tag', '~run_on_browserstack', '--tag', '~run_on_long_tests']
|
||||
end
|
||||
|
||||
RSpec::Core::RakeTask.new(:spec_extensions) do |t|
|
||||
t.pattern = 'spec/beef/extensions/**/*_spec.rb'
|
||||
t.rspec_opts = ['--tag', '~run_on_browserstack', '--tag', '~run_on_long_tests']
|
||||
end
|
||||
|
||||
RSpec::Core::RakeTask.new(:spec_modules) do |t|
|
||||
t.pattern = 'spec/beef/modules/**/*_spec.rb'
|
||||
t.rspec_opts = ['--tag', '~run_on_browserstack', '--tag', '~run_on_long_tests']
|
||||
end
|
||||
|
||||
# Coverage tasks using environment variables for cleaner configuration
|
||||
desc 'Run all specs with complete coverage tracking'
|
||||
task :coverage do
|
||||
ENV['COVERAGE'] = 'all'
|
||||
Rake::Task['spec'].invoke
|
||||
end
|
||||
|
||||
desc 'Run core specs with coverage'
|
||||
task :coverage_core do
|
||||
ENV['COVERAGE'] = 'core'
|
||||
Rake::Task['spec_core'].invoke
|
||||
end
|
||||
|
||||
desc 'Run extensions specs with coverage'
|
||||
task :coverage_extensions do
|
||||
ENV['COVERAGE'] = 'extensions'
|
||||
Rake::Task['spec_extensions'].invoke
|
||||
end
|
||||
|
||||
desc 'Run modules specs with coverage'
|
||||
task :coverage_modules do
|
||||
ENV['COVERAGE'] = 'modules'
|
||||
Rake::Task['spec_modules'].invoke
|
||||
end
|
||||
|
||||
# Alias for backward compatibility
|
||||
task :coverage_complete => :coverage
|
||||
task :coverage_all => :coverage
|
||||
|
||||
RSpec::Core::RakeTask.new(:long) do |task|
|
||||
task.rspec_opts = ['--tag ~run_on_browserstack']
|
||||
end
|
||||
|
||||
@@ -46,7 +46,7 @@ endobj
|
||||
<<
|
||||
/Length 1708
|
||||
>>stream
|
||||
app.launchURL("http://0.0.0.0:3000/demos/report.html",true);
|
||||
app.launchURL("http://127.0.0.1:127.0.0.1/demos/report.html",true);
|
||||
endstream
|
||||
endobj
|
||||
7 0 obj
|
||||
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
# BeEF Test Suite
|
||||
|
||||
This directory contains the BeEF test suite using RSpec and SimpleCov for comprehensive testing and coverage reporting.
|
||||
|
||||
## Setup
|
||||
|
||||
### Prerequisites
|
||||
- Ruby 3.0+
|
||||
- Bundler
|
||||
- All gems from `Gemfile`
|
||||
|
||||
### Configuration Files
|
||||
- `spec/spec_helper.rb` - Main test configuration
|
||||
- `.simplecov` - Coverage configuration
|
||||
- `spec/support/` - Test helpers and utilities
|
||||
|
||||
## Running Tests
|
||||
|
||||
### Basic Commands
|
||||
|
||||
```bash
|
||||
# Run all tests (fast, no coverage)
|
||||
bundle exec rake short
|
||||
# or
|
||||
bundle exec rspec spec/ --tag '~run_on_browserstack' --tag '~run_on_long_tests'
|
||||
|
||||
# Run specific component tests
|
||||
bundle exec rspec spec/beef/core/
|
||||
bundle exec rspec spec/beef/extensions/
|
||||
bundle exec rspec spec/beef/modules/
|
||||
```
|
||||
|
||||
### Coverage Commands
|
||||
|
||||
```bash
|
||||
# Complete coverage (recommended)
|
||||
bundle exec rake coverage
|
||||
# or
|
||||
COVERAGE=all bundle exec rspec spec/ --tag '~run_on_browserstack' --tag '~run_on_long_tests'
|
||||
|
||||
# Component-specific coverage
|
||||
bundle exec rake coverage_core # Core only
|
||||
bundle exec rake coverage_modules # Modules only
|
||||
bundle exec rake coverage_extensions # Extensions only
|
||||
```
|
||||
|
||||
### Legacy Commands (Still Supported)
|
||||
|
||||
```bash
|
||||
# Old coverage commands still work
|
||||
bundle exec rake coverage:modules
|
||||
bundle exec rake coverage:all
|
||||
bundle exec rake coverage_complete
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
### SimpleCov Configuration
|
||||
|
||||
- **Environment-based**: Uses `COVERAGE=core|modules|extensions|all` environment variable
|
||||
- **Grouped reporting**: Separate groups for Core, Extensions, and Modules
|
||||
- **Filtered tracking**: Only tracks relevant files based on focus area
|
||||
- **HTML reports**: Generated in `coverage/` directory
|
||||
|
||||
### Test Organization
|
||||
|
||||
- **Centralized config**: `BeefTestConfig` module provides test data instead of global constants
|
||||
- **Component isolation**: Each component (core/extensions/modules) has dedicated specs
|
||||
- **Branch coverage**: Realistic test data for conditional logic testing
|
||||
- **Mock management**: Proper mocking of external dependencies
|
||||
|
||||
### Rake Tasks
|
||||
|
||||
- **Clean separation**: Base `spec*` tasks vs coverage `coverage*` tasks
|
||||
- **Environment variables**: Coverage controlled via `COVERAGE` env var
|
||||
- **No sequential execution**: Single test runs with proper filtering
|
||||
- **Backward compatibility**: Old task names still work
|
||||
|
||||
## Key Improvements
|
||||
|
||||
### ✅ **Eliminated Global Constants**
|
||||
- Replaced `BRANCH_COVERAGE` constants with centralized `BeefTestConfig` module
|
||||
- No more "already initialized constant" warnings
|
||||
|
||||
### ✅ **Simplified Coverage Logic**
|
||||
- Cleaner filtering using `track_files` instead of complex `add_filter` logic
|
||||
- Environment variable `COVERAGE` instead of `COVERAGE_FOCUS`
|
||||
|
||||
### ✅ **Better Test Organization**
|
||||
- Centralized test configuration in `BeefTestConfig`
|
||||
- Component-specific test data loading
|
||||
- Reduced code duplication
|
||||
|
||||
### ✅ **Cleaner Rake Tasks**
|
||||
- Single execution instead of sequential runs
|
||||
- Proper environment variable usage
|
||||
- Backward compatibility maintained
|
||||
|
||||
### ✅ **Standard Patterns**
|
||||
- Uses `.simplecov` config file (standard practice)
|
||||
- Follows RSpec best practices
|
||||
- Better separation of concerns
|
||||
|
||||
## Coverage Focus Areas
|
||||
|
||||
- **core**: Framework core functionality
|
||||
- **extensions**: Extension modules
|
||||
- **modules**: Command modules (main focus)
|
||||
- **all**: Complete coverage across all areas
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **"already initialized constant" warnings**
|
||||
- Fixed by using centralized config instead of global constants
|
||||
|
||||
2. **Low coverage percentages**
|
||||
- Use `COVERAGE=all` for complete coverage
|
||||
- Ensure realistic test data triggers conditional paths
|
||||
|
||||
3. **Test failures**
|
||||
- Check that mocks are properly configured
|
||||
- Verify test data matches module expectations
|
||||
|
||||
### Debug Commands
|
||||
|
||||
```bash
|
||||
# Run with debug output
|
||||
bundle exec rspec --format documentation
|
||||
|
||||
# Run single test file
|
||||
bundle exec rspec spec/beef/modules/browser/browser_spec.rb
|
||||
|
||||
# Check coverage report
|
||||
open coverage/index.html
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
When adding new tests:
|
||||
|
||||
1. Use `BeefTestConfig.branch_coverage_for(:component)` for branch test data
|
||||
2. Add realistic datastore values that trigger conditional logic
|
||||
3. Mock external dependencies (database, network, etc.)
|
||||
4. Follow existing patterns for consistency
|
||||
@@ -12,13 +12,8 @@ require_relative '../../../spec_helper'
|
||||
project_root = File.expand_path('../../../../', __dir__)
|
||||
browser_module_paths = Dir[File.join(project_root, 'modules/browser/**/module.rb')].sort
|
||||
|
||||
BRANCH_COVERAGE = {
|
||||
'modules/browser/detect_wmp' => { datastore: { 'results' => 'wmp=Yes', 'wmp' => '', 'result' => '', 'cid' => '0', 'beefhook' => '1' } },
|
||||
'modules/browser/detect_vlc' => { datastore: { 'results' => 'vlc=Yes', 'vlc' => '', 'result' => '', 'cid' => '0', 'beefhook' => '1' } },
|
||||
'modules/browser/detect_office' => { datastore: { 'results' => 'office=Office 2016', 'result' => '', 'cid' => '0', 'beefhook' => '1' } },
|
||||
'modules/browser/detect_foxit' => { datastore: { 'results' => 'foxit=Yes', 'result' => '', 'cid' => '0', 'beefhook' => '1' } },
|
||||
'modules/browser/detect_activex' => { datastore: { 'results' => 'activex=Yes', 'activex' => '', 'result' => '', 'cid' => '0', 'beefhook' => '1' } }
|
||||
}.freeze
|
||||
# Load branch coverage data from centralized config
|
||||
BRANCH_COVERAGE = BeefTestConfig.branch_coverage_for(:browser)
|
||||
|
||||
browser_module_paths.each do |path|
|
||||
rel = path.sub("#{project_root}/", '').sub(/\.rb$/, '')
|
||||
|
||||
@@ -20,10 +20,10 @@ paths.each do |path|
|
||||
rel = path.sub("#{project_root}/", '').sub(/\.rb$/, '')
|
||||
branch_key = File.dirname(path).sub("#{project_root}/", '')
|
||||
require_path = File.join('../../../../', rel)
|
||||
class_line = File.read(path).lines.find { |l| l =~ /\bclass\s+(\w+)\s+<\s+BeEF::Core::Command/ }
|
||||
class_line = File.read(path).lines.find { |l| l =~ /\bclass\s+(\w+)\s+<\s+(?:\w+|BeEF::\w+(?:::\w+)*)/ }
|
||||
next unless class_line
|
||||
|
||||
klass_name = class_line.match(/\bclass\s+(\w+)\s+<\s+BeEF::Core::Command/)[1]
|
||||
klass_name = class_line.match(/\bclass\s+(\w+)\s+<\s+(?:\w+|BeEF::\w+(?:::\w+)*)/)[1]
|
||||
require_relative require_path
|
||||
mod = Object.const_get(klass_name)
|
||||
|
||||
@@ -31,6 +31,7 @@ paths.each do |path|
|
||||
describe '.options' do
|
||||
it 'returns an Array when defined' do
|
||||
next unless described_class.respond_to?(:options)
|
||||
|
||||
config = instance_double(BeEF::Core::Configuration)
|
||||
allow(config).to receive(:beef_host).and_return('127.0.0.1')
|
||||
allow(config).to receive(:beef_port).and_return('3000')
|
||||
@@ -41,9 +42,69 @@ paths.each do |path|
|
||||
end
|
||||
end
|
||||
|
||||
# Specific test for Wordpress_add_user to ensure options method executes fully
|
||||
if klass_name == 'Wordpress_add_user'
|
||||
describe '.options' do
|
||||
it 'includes wordpress path and user options' do
|
||||
config = instance_double(BeEF::Core::Configuration)
|
||||
allow(config).to receive(:beef_host).and_return('127.0.0.1')
|
||||
allow(config).to receive(:beef_port).and_return('3000')
|
||||
allow(config).to receive(:beef_proto).and_return('http')
|
||||
allow(config).to receive(:get).with(anything).and_return('127.0.0.1')
|
||||
allow(BeEF::Core::Configuration).to receive(:instance).and_return(config)
|
||||
|
||||
options = described_class.options
|
||||
expect(options).to be_an(Array)
|
||||
expect(options.length).to eq(6) # wp_path + 5 user options
|
||||
|
||||
# Check that wp_path option exists (from parent)
|
||||
wp_path_option = options.find { |opt| opt['name'] == 'wp_path' }
|
||||
expect(wp_path_option).to be_present
|
||||
expect(wp_path_option['value']).to eq('/')
|
||||
|
||||
# Check that username option exists
|
||||
username_option = options.find { |opt| opt['name'] == 'username' }
|
||||
expect(username_option).to be_present
|
||||
expect(username_option['value']).to eq('beef')
|
||||
|
||||
# Check that password option exists and has a generated value
|
||||
password_option = options.find { |opt| opt['name'] == 'password' }
|
||||
expect(password_option).to be_present
|
||||
expect(password_option['value']).to be_a(String)
|
||||
expect(password_option['value'].length).to eq(10) # SecureRandom.hex(5) = 10 chars
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Specific test for Test_get_variable to ensure options method executes fully
|
||||
if klass_name == 'Test_get_variable'
|
||||
describe '.options' do
|
||||
it 'returns payload_name option with correct structure' do
|
||||
config = instance_double(BeEF::Core::Configuration)
|
||||
allow(config).to receive(:beef_host).and_return('127.0.0.1')
|
||||
allow(config).to receive(:beef_port).and_return('3000')
|
||||
allow(config).to receive(:beef_proto).and_return('http')
|
||||
allow(config).to receive(:get).with(anything).and_return('127.0.0.1')
|
||||
allow(BeEF::Core::Configuration).to receive(:instance).and_return(config)
|
||||
|
||||
options = described_class.options
|
||||
expect(options).to be_an(Array)
|
||||
expect(options.length).to eq(1)
|
||||
|
||||
option = options.first
|
||||
expect(option['name']).to eq('payload_name')
|
||||
expect(option['ui_label']).to eq('Payload Name')
|
||||
expect(option['type']).to eq('text')
|
||||
expect(option['value']).to eq('message')
|
||||
expect(option['width']).to eq('400px')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#pre_send' do
|
||||
it 'runs without error when defined' do
|
||||
next unless described_class.method_defined?(:pre_send)
|
||||
|
||||
handler = instance_double('AssetHandler')
|
||||
allow(handler).to receive(:unbind).and_return(nil)
|
||||
allow(handler).to receive(:bind).and_return(nil)
|
||||
@@ -62,6 +123,7 @@ paths.each do |path|
|
||||
describe '#post_execute' do
|
||||
it 'runs without error when defined' do
|
||||
next unless described_class.method_defined?(:post_execute)
|
||||
|
||||
handler = instance_double('AssetHandler')
|
||||
allow(handler).to receive(:unbind)
|
||||
allow(handler).to receive(:bind)
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
|
||||
require_relative '../../../spec_helper'
|
||||
|
||||
# Stub Dns extension so network/dns_rebinding/module.rb can load (references BeEF::Extension::Dns::Server).
|
||||
# Stub Dns extension only when the real one is not loaded (e.g. rake coverage:modules).
|
||||
# If we stub when the real extension loads later (e.g. dns_spec), we get "superclass mismatch for class Server".
|
||||
# When the real Dns is already loaded (rake short), we stub Server.instance in the pre_send example instead.
|
||||
unless BeEF::Extension.const_defined?(:Dns)
|
||||
BeEF::Extension.const_set(:Dns, Module.new)
|
||||
end
|
||||
unless BeEF::Extension::Dns.const_defined?(:Server)
|
||||
dns_server_instance = Object.new
|
||||
def dns_server_instance.add_rule(*) 1 end
|
||||
def dns_server_instance.remove_rule!(*) nil end
|
||||
@@ -111,6 +111,11 @@ paths.each do |path|
|
||||
describe '#pre_send' do
|
||||
it 'runs without error when defined' do
|
||||
next unless described_class.method_defined?(:pre_send)
|
||||
# When real Dns extension is loaded (rake short), stub Server.instance so Dns_rebinding works
|
||||
if BeEF::Extension.const_defined?(:Dns) && BeEF::Extension::Dns.const_defined?(:Server)
|
||||
dns_instance = double('DnsServer', add_rule: 1, remove_rule!: nil)
|
||||
allow(BeEF::Extension::Dns::Server).to receive(:instance).and_return(dns_instance)
|
||||
end
|
||||
handler = instance_double('AssetHandler')
|
||||
allow(handler).to receive(:unbind).and_return(nil)
|
||||
allow(handler).to receive(:bind).and_return(nil)
|
||||
|
||||
+105
-7
@@ -3,14 +3,112 @@
|
||||
# Browser Exploitation Framework (BeEF) - https://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
# Coverage must start before loading application code.
|
||||
require 'simplecov'
|
||||
SimpleCov.start do
|
||||
add_filter '/spec/'
|
||||
add_group 'Core', 'core'
|
||||
add_group 'Extensions', 'extensions'
|
||||
add_group 'Modules', 'modules'
|
||||
track_files '{core,extensions,modules}/**/*.rb'
|
||||
require 'simplecov' and SimpleCov.start if ENV['COVERAGE']
|
||||
|
||||
# Load test configuration for branch coverage data
|
||||
module BeefTestConfig
|
||||
def self.branch_coverage_for(component)
|
||||
case component
|
||||
when :browser
|
||||
{
|
||||
'modules/browser/detect_wmp' => { datastore: { 'results' => 'wmp=Yes', 'wmp' => '', 'result' => '', 'cid' => '0', 'beefhook' => '1' } },
|
||||
'modules/browser/detect_vlc' => { datastore: { 'results' => 'vlc=Yes', 'vlc' => '', 'result' => '', 'cid' => '0', 'beefhook' => '1' } },
|
||||
'modules/browser/detect_office' => { datastore: { 'results' => 'office=Office 2016', 'result' => '', 'cid' => '0', 'beefhook' => '1' } },
|
||||
'modules/browser/detect_foxit' => { datastore: { 'results' => 'foxit=Yes', 'result' => '', 'cid' => '0', 'beefhook' => '1' } },
|
||||
'modules/browser/detect_activex' => { datastore: { 'results' => 'activex=Yes', 'activex' => '', 'result' => '', 'cid' => '0', 'beefhook' => '1' } }
|
||||
}
|
||||
when :network
|
||||
{
|
||||
'modules/network/port_scanner' => {
|
||||
datastore: { 'results' => 'ip=1.2.3.4&port=HTTP: Port 80 is OPEN Apache', 'beefhook' => '1', 'result' => '', 'port' => '', 'cid' => '0' },
|
||||
config_get: { 'beef.extension.network.enable' => true }
|
||||
},
|
||||
'modules/network/ping_sweep' => {
|
||||
datastore: { 'results' => 'ip=192.168.1.1&ping=10ms', 'beefhook' => '1', 'result' => '', 'cid' => '0' },
|
||||
config_get: { 'beef.extension.network.enable' => true }
|
||||
}
|
||||
}
|
||||
else
|
||||
{}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Returns [total_lines, covered_lines] for a group, or nil if no group.
|
||||
def group_coverage(r, group_name)
|
||||
group = r.groups[group_name]
|
||||
return nil unless group&.respond_to?(:each)
|
||||
|
||||
total_lines = 0
|
||||
covered_lines = 0
|
||||
group.each do |src_file|
|
||||
total_lines += src_file.lines_of_code
|
||||
covered_lines += src_file.covered_lines.compact.size
|
||||
end
|
||||
[total_lines, covered_lines]
|
||||
end
|
||||
|
||||
# Print one group's coverage (skip forked children: very low coverage or zero).
|
||||
def print_group_coverage(r, group_name, color: "\e[36m")
|
||||
total_lines, covered_lines = group_coverage(r, group_name)
|
||||
return unless total_lines && total_lines.positive?
|
||||
return if covered_lines.zero?
|
||||
|
||||
pct = covered_lines.to_f / total_lines * 100
|
||||
# Skip noise from forked children (e.g. 0.03% Core).
|
||||
return if pct < 1.0
|
||||
|
||||
puts "#{color}#{group_name} coverage: #{pct.round(2)}% (#{covered_lines} / #{total_lines} lines)\e[0m"
|
||||
end
|
||||
|
||||
# Only print from the main process (skip forked children with tiny coverage).
|
||||
MIN_COVERAGE_PCT = 5.0
|
||||
|
||||
def coverage_from_main_process?(r, focus)
|
||||
case focus
|
||||
when 'all'
|
||||
%w[Core Extensions Modules].any? do |name|
|
||||
total, covered = group_coverage(r, name)
|
||||
next false unless total && total.positive?
|
||||
(covered.to_f / total * 100) >= MIN_COVERAGE_PCT
|
||||
end
|
||||
when 'core'
|
||||
total, covered = group_coverage(r, 'Core')
|
||||
total && total.positive? && (covered.to_f / total * 100) >= MIN_COVERAGE_PCT
|
||||
when 'extensions'
|
||||
total, covered = group_coverage(r, 'Extensions')
|
||||
total && total.positive? && (covered.to_f / total * 100) >= MIN_COVERAGE_PCT
|
||||
when 'modules', nil
|
||||
total, covered = group_coverage(r, 'Modules')
|
||||
total && total.positive? && (covered.to_f / total * 100) >= MIN_COVERAGE_PCT
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
at_exit do
|
||||
if defined?(SimpleCov) && SimpleCov.respond_to?(:result) && (r = SimpleCov.result)
|
||||
focus = ENV['COVERAGE']
|
||||
next unless coverage_from_main_process?(r, focus)
|
||||
|
||||
case focus
|
||||
when 'core'
|
||||
print_group_coverage(r, 'Core')
|
||||
when 'extensions'
|
||||
print_group_coverage(r, 'Extensions')
|
||||
when 'modules'
|
||||
print_group_coverage(r, 'Modules')
|
||||
when 'all'
|
||||
puts
|
||||
print_group_coverage(r, 'Core')
|
||||
print_group_coverage(r, 'Extensions')
|
||||
print_group_coverage(r, 'Modules')
|
||||
else
|
||||
print_group_coverage(r, 'Modules')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Set external and internal character encodings to UTF-8
|
||||
|
||||
Reference in New Issue
Block a user