Created
October 19, 2013 03:13
-
-
Save mockdeep/7051285 to your computer and use it in GitHub Desktop.
Script to convert spec files to mutation testing format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'active_support/inflector' | |
inflectors_path = File.expand_path('./config/initializers/inflections.rb') | |
load inflectors_path if File.exist?(inflectors_path) | |
class Mutagen | |
def initialize(path) | |
file_match_expression = File.join(File.expand_path(path), '**/*.rb') | |
@source_files = Dir.glob(file_match_expression).map do |file_path| | |
SourceFile.new(file_path, path) | |
end | |
end | |
def mutate! | |
@source_files.each do |source_file| | |
dir_path = source_file.dir_path | |
Dir.mkdir(dir_path) unless Dir.exist?(dir_path) | |
source_file.spec_groups.each do |spec_group| | |
dir_path = spec_group.dir_path | |
Dir.mkdir(dir_path) unless Dir.exist?(dir_path) | |
File.write(spec_group.target_path, spec_group.text) | |
end | |
end | |
end | |
end | |
class SourceFile | |
def initialize(file_path, base_path) | |
@file_path = file_path | |
@base_path = base_path | |
end | |
def old_spec_groups | |
@spec_groups ||= group_names.map do |group_name| | |
SpecGroup.new(group_name, dir_path, class_name) | |
end | |
end | |
def dir_path | |
File.join(@base_path, class_path) | |
end | |
def class_name | |
class_path.split('/').last.classify | |
end | |
def class_path | |
@file_path.match(/#{@base_path}\/(.*)_spec\.rb/).captures.first | |
end | |
def spec_groups | |
@spec_groups = [] | |
block = '' | |
pre_block_text = '' | |
block_started = false | |
pre_block = false | |
block_name = '' | |
file_text.lines.each do |line| | |
if line.match(/^ describe '(\S*)' do$/) | |
block_name = $1 | |
block_started = true | |
unless pre_block_text.strip == '' | |
@spec_groups << SpecGroup.new('__ungrouped', dir_path, class_name, pre_block_text) | |
end | |
pre_block = false | |
next | |
elsif !block_started && line.match(/^describe (\S*) do$/) | |
pre_block = true | |
pre_block_text = '' | |
next | |
elsif !block_started && pre_block | |
pre_block_text << line | |
next | |
elsif !block_started | |
next | |
end | |
if line.match(/^ end$/) | |
@spec_groups << SpecGroup.new(block_name, dir_path, class_name, block) | |
block = '' | |
block_started = false | |
else | |
line = line[2..-1] || "\n" | |
block << line | |
end | |
end | |
@spec_groups | |
end | |
private | |
def group_names | |
file_text.scan(/^ describe '(.*)' do$/).flatten.uniq | |
end | |
def file_text | |
file_text = File.read(@file_path) | |
end | |
end | |
class SpecGroup | |
attr_reader :name, :class_name, :base_path, :block | |
def initialize(name, base_path, class_name, block) | |
raise 'no spaces!' if name.match(/ /) | |
@name = name | |
@base_path = base_path | |
@class_name = class_name | |
@block = block | |
end | |
def target_path | |
File.join(dir_path, file_name) | |
end | |
def dir_path | |
[base_path, path_extension].compact.join('/') | |
end | |
def file_name | |
"#{stripped_name}#{modifier}_spec.rb" | |
end | |
def text | |
<<EOF | |
require 'spec_helper' | |
describe #{class_name}, '#{name}' do | |
#{block} | |
end | |
EOF | |
end | |
def path_extension | |
'class_methods' if name.match(/^\..*/) | |
end | |
def stripped_name | |
plain_name = name.match(/(\w+)/) | |
plain_name && plain_name.captures.first | |
end | |
def modifier | |
case name | |
when /<=>/ | |
'spaceship_operator' | |
when /!$/ | |
'_bang' | |
when /\?$/ | |
'_predicate' | |
when /=$/ | |
'_writer' | |
else | |
'' | |
end | |
end | |
end | |
mutagen = Mutagen.new('spec/models') | |
mutagen.mutate! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'd recommend looking at using
Pathname
objects to represent file and directory paths rather thanString
objects.