codespicuous 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +7 -0
- data/LICENSE +29 -0
- data/README.md +2 -0
- data/Rakefile +6 -0
- data/bin/codespicuous +4 -0
- data/bin/filezilla/codespicuous.yaml +23 -0
- data/bin/filezilla/committers.csv +4 -0
- data/bin/filezilla/svnlog/filezilla.log +3939 -0
- data/bin/filezilla/svnlog/python.log +3 -0
- data/bin/filezilla/svnlog/xiph.log +265 -0
- data/codespicuous.gemspec +22 -0
- data/lib/codespicuous.rb +38 -0
- data/lib/codespicuous/codespicuous.rb +55 -0
- data/lib/codespicuous/codespicuous_config.rb +35 -0
- data/lib/codespicuous/codespicuousconfigurator.rb +136 -0
- data/lib/codespicuous/commandrunner.rb +13 -0
- data/lib/codespicuous/commithistory.rb +71 -0
- data/lib/codespicuous/commithistory_builder.rb +49 -0
- data/lib/codespicuous/commits.rb +147 -0
- data/lib/codespicuous/commitstatistics.rb +245 -0
- data/lib/codespicuous/committer.rb +105 -0
- data/lib/codespicuous/danielparser.rb +31 -0
- data/lib/codespicuous/dateutil.rb +18 -0
- data/lib/codespicuous/metrics_generator.rb +22 -0
- data/lib/codespicuous/metrics_generator_csv.rb +67 -0
- data/lib/codespicuous/metrics_generator_daniel.rb +13 -0
- data/lib/codespicuous/participantsparser_from_csv.rb +37 -0
- data/lib/codespicuous/repositories.rb +80 -0
- data/lib/codespicuous/repository_lister.rb +8 -0
- data/lib/codespicuous/svn_client.rb +14 -0
- data/lib/codespicuous/svn_data_collector.rb +50 -0
- data/lib/codespicuous/svn_log_parser.rb +100 -0
- data/lib/codespicuous/teams.rb +99 -0
- data/lib/codespicuous/version.rb +4 -0
- data/spec/codespicuous_spec.rb +81 -0
- data/spec/codespicuousconfigurator_spec.rb +202 -0
- data/spec/commithistories_data.rb +46 -0
- data/spec/commithistory_spec.rb +57 -0
- data/spec/commits_spec.rb +93 -0
- data/spec/committers_spec.rb +66 -0
- data/spec/danielparser_spec.rb +12 -0
- data/spec/integration_filezilla_spec.rb +41 -0
- data/spec/metrics_generator_csv_spec.rb +91 -0
- data/spec/metrics_generator_daniel_spec.rb +10 -0
- data/spec/metrics_generator_spec.rb +35 -0
- data/spec/repositories_spec.rb +29 -0
- data/spec/svn_client_spec.rb +16 -0
- data/spec/svn_data_collector_spec.rb +93 -0
- data/spec/svn_log_parser_spec.rb +141 -0
- data/spec/teams_spec.rb +16 -0
- metadata +142 -0
@@ -0,0 +1,100 @@
|
|
1
|
+
|
2
|
+
require 'rexml/document'
|
3
|
+
|
4
|
+
class SVNLogParser
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@commits = Commits.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def xml_to_parse(xml_string)
|
11
|
+
@xml_to_parse = xml_string
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse(xml_to_parse = nil)
|
15
|
+
@xml_to_parse = xml_to_parse if xml_to_parse
|
16
|
+
|
17
|
+
xml = REXML::Document.new(@xml_to_parse)
|
18
|
+
validate_xml(xml)
|
19
|
+
|
20
|
+
xml.elements.each( "*/logentry" ) do |logentry|
|
21
|
+
commit = create_commit_from_log_entry(logentry)
|
22
|
+
@commits.add(commit)
|
23
|
+
end
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_commit_from_log_entry(logentry)
|
28
|
+
commit = Commit.new
|
29
|
+
commit.revision = logentry.attributes["revision"]
|
30
|
+
commit.author = logentry.elements["author"].text
|
31
|
+
commit.message = logentry.elements["msg"].text
|
32
|
+
commit.date = DateTime.parse(logentry.elements["date"].text)
|
33
|
+
commit.changes = create_commit_changes_from_log_entry(logentry)
|
34
|
+
commit
|
35
|
+
end
|
36
|
+
|
37
|
+
def extract_change_type(path)
|
38
|
+
return :modified if path.attributes["action"] == "M"
|
39
|
+
return :added if path.attributes["action"] == "A"
|
40
|
+
return :deleted if path.attributes["action"] == "D"
|
41
|
+
return :renamed if path.attributes["action"] == "R"
|
42
|
+
end
|
43
|
+
|
44
|
+
def extract_kind(path)
|
45
|
+
return :file if path.attributes["kind"] == "file"
|
46
|
+
return :dir if path.attributes["kind"] == "dir"
|
47
|
+
end
|
48
|
+
|
49
|
+
def create_commit_changes_from_log_entry(logentry)
|
50
|
+
changes = []
|
51
|
+
logentry.elements.each("*/path") { |path|
|
52
|
+
change = Change.new
|
53
|
+
change.type = extract_change_type(path)
|
54
|
+
change.kind = extract_kind(path)
|
55
|
+
change.property_changed if path.attributes["prop-mods"] == "true"
|
56
|
+
change.copyfrom = path.attributes["copyfrom-path"]
|
57
|
+
change.copyrev = path.attributes["copyfrom-rev"]
|
58
|
+
change.file = path.text
|
59
|
+
changes << change
|
60
|
+
}
|
61
|
+
changes
|
62
|
+
end
|
63
|
+
|
64
|
+
def validate_xml(xml)
|
65
|
+
non_logentries = xml.elements["log"].elements.collect { |e| e.name unless e.name == "logentry" }.compact
|
66
|
+
non_logentries.each { |e| raise("Unexpected log entry: " + e) }
|
67
|
+
|
68
|
+
xml.elements.each( "*/logentry" ) do |logentry|
|
69
|
+
validate_log_entry(logentry)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def validate_log_entry logentry
|
74
|
+
invalid_attributes = logentry.attributes.collect { |a| a[0] unless a[0] == "revision" }.compact
|
75
|
+
invalid_attributes.each { |a| raise ("Unexpected attributes log entry: " + a) }
|
76
|
+
|
77
|
+
invalid_elements = logentry.elements.collect { |e| e.name unless ["author", "date", "paths", "msg"].include? e.name }.compact
|
78
|
+
invalid_elements.each { |e| raise ("Unexpected element in log entry: " + e) }
|
79
|
+
|
80
|
+
logentry.elements.each("*/path") { |path|
|
81
|
+
validate_path path
|
82
|
+
}
|
83
|
+
end
|
84
|
+
|
85
|
+
def validate_path path
|
86
|
+
path.elements.each { |e| raise ("Unexpected element in path: " + e.name) }
|
87
|
+
|
88
|
+
invalid_attributes = path.attributes.collect { |a| a[0] unless ["action", "prop-mods", "text-mods", "kind", "copyfrom-path", "copyfrom-rev"].include? a[0] }.compact
|
89
|
+
invalid_attributes.each { |a| raise ("Unexpected attributes in path: " + a) }
|
90
|
+
|
91
|
+
raise("Unexpected value to attribute action in path: " + path.attributes["action"]) unless ["R", "M", "A", "D"].include?(path.attributes["action"])
|
92
|
+
raise("Unexpected value to attribute kind in path: " + path.attributes["kind"]) unless ["file", "dir"].include?(path.attributes["kind"])
|
93
|
+
|
94
|
+
puts "Unexpected value to attribute text-mods in path: " + path.attributes["text-mods"] if path.attributes["text-mods"] == "false" and not ["D", "R"].include?(path.attributes["action"]) and path.attributes["kind"] != "dir"
|
95
|
+
end
|
96
|
+
|
97
|
+
def commits
|
98
|
+
@commits
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
|
2
|
+
class Team
|
3
|
+
|
4
|
+
attr_accessor :name
|
5
|
+
|
6
|
+
def initialize(name)
|
7
|
+
@name = name
|
8
|
+
@members = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_member(member)
|
12
|
+
@members[member.username] = member
|
13
|
+
member.team = self
|
14
|
+
end
|
15
|
+
|
16
|
+
def members
|
17
|
+
@members.values
|
18
|
+
end
|
19
|
+
|
20
|
+
def each_member
|
21
|
+
@members.values.each { |member|
|
22
|
+
yield member
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def amount_of_members
|
27
|
+
@members.size
|
28
|
+
end
|
29
|
+
|
30
|
+
def member_usernames
|
31
|
+
@members.keys
|
32
|
+
end
|
33
|
+
|
34
|
+
def <=> other
|
35
|
+
@name <=> other.name
|
36
|
+
end
|
37
|
+
|
38
|
+
def ==(team)
|
39
|
+
name == team.name && members == team.members
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Teams
|
44
|
+
|
45
|
+
attr_reader :teams
|
46
|
+
|
47
|
+
def initialize
|
48
|
+
@teams = {}
|
49
|
+
end
|
50
|
+
|
51
|
+
def find_by_name(name)
|
52
|
+
@teams[name]
|
53
|
+
end
|
54
|
+
|
55
|
+
def team_names
|
56
|
+
@teams.keys
|
57
|
+
end
|
58
|
+
|
59
|
+
def each
|
60
|
+
@teams.values.sort.each { |team|
|
61
|
+
yield team
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def map(&block)
|
66
|
+
@teams.values.map(&block)
|
67
|
+
end
|
68
|
+
|
69
|
+
def each_member
|
70
|
+
@teams.values.each { |team|
|
71
|
+
team.each_member { |member|
|
72
|
+
yield team, member
|
73
|
+
}
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
def team(name)
|
78
|
+
@teams[name] ||= Team.new(name)
|
79
|
+
end
|
80
|
+
|
81
|
+
def add(team)
|
82
|
+
@teams[team.name] = team
|
83
|
+
end
|
84
|
+
|
85
|
+
def amount
|
86
|
+
@teams.size
|
87
|
+
end
|
88
|
+
|
89
|
+
def member_usernames(team_name = nil)
|
90
|
+
@teams.values.collect { |team|
|
91
|
+
team.member_usernames if team.name == team_name || team_name == nil
|
92
|
+
}.compact.flatten
|
93
|
+
end
|
94
|
+
|
95
|
+
def ==(teams)
|
96
|
+
@teams == teams.teams
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
@@ -0,0 +1,81 @@
|
|
1
|
+
|
2
|
+
describe "Codespicuous command line" do
|
3
|
+
|
4
|
+
subject {Codespicuous.new}
|
5
|
+
|
6
|
+
it "prints an error message when no config it present" do
|
7
|
+
expect(subject).to receive(:puts).with("Stage 1: Configuring")
|
8
|
+
expect($stdout).to receive(:puts).with("** Error: No repositories configured in \"codespicuous.yaml\"")
|
9
|
+
|
10
|
+
expect(subject.run([])).to eq false
|
11
|
+
end
|
12
|
+
|
13
|
+
it "creates a configurator, collect data, and lists the repositories the people committed to" do
|
14
|
+
subject.config.list_repositories = true
|
15
|
+
|
16
|
+
expect(subject).to receive(:puts).with("Stage 1: Configuring")
|
17
|
+
expect(subject).to receive(:configure).and_return(true)
|
18
|
+
expect(subject).to receive(:puts).with("Stage 2: Collecting input data")
|
19
|
+
expect(subject).to receive(:collect)
|
20
|
+
expect(subject).to receive(:puts).with("Stage 3: Listing repositories committed to")
|
21
|
+
expect(subject).to receive(:list_committed_repositories)
|
22
|
+
|
23
|
+
expect(subject.run([])).to eq true
|
24
|
+
end
|
25
|
+
|
26
|
+
it "creates a configurator, collect data, and generate output" do
|
27
|
+
expect(subject).to receive(:puts).with("Stage 1: Configuring")
|
28
|
+
expect(subject).to receive(:configure).and_return(true)
|
29
|
+
expect(subject).to receive(:puts).with("Stage 2: Collecting input data")
|
30
|
+
expect(subject).to receive(:collect)
|
31
|
+
expect(subject).to receive(:puts).with("Stage 3: Generating output")
|
32
|
+
expect(subject).to receive(:generate_output)
|
33
|
+
|
34
|
+
expect(subject.run([])).to eq true
|
35
|
+
end
|
36
|
+
|
37
|
+
it "configures the config data" do
|
38
|
+
configurator = CodespicuousConfigurator.new(subject.config)
|
39
|
+
repositories = Repositories.new
|
40
|
+
committers = Committers.new
|
41
|
+
teams = Teams.new
|
42
|
+
|
43
|
+
expect(CodespicuousConfigurator).to receive(:new).and_return(configurator)
|
44
|
+
expect(configurator).to receive(:configure).with(["argv"]).and_return(true)
|
45
|
+
|
46
|
+
expect(configurator).to receive(:repositories).and_return(repositories)
|
47
|
+
expect(configurator).to receive(:committers).and_return(committers)
|
48
|
+
expect(configurator).to receive(:teams).and_return(teams)
|
49
|
+
|
50
|
+
subject.configure(["argv"])
|
51
|
+
expect(subject.committers).to be committers
|
52
|
+
expect(subject.repositories).to be repositories
|
53
|
+
expect(subject.teams).to be teams
|
54
|
+
end
|
55
|
+
|
56
|
+
it "collects the input data" do
|
57
|
+
collector = SVNDataCollector.new(subject.config)
|
58
|
+
commit_history = CommitHistory.new
|
59
|
+
expect(SVNDataCollector).to receive(:new).and_return(collector)
|
60
|
+
expect(collector).to receive(:collect_commit_history).with(subject.repositories).and_return(commit_history)
|
61
|
+
|
62
|
+
subject.collect
|
63
|
+
|
64
|
+
expect(subject.commit_history).to eq commit_history
|
65
|
+
end
|
66
|
+
|
67
|
+
it "generates output" do
|
68
|
+
generator = MetricsGenerator.new
|
69
|
+
expect(MetricsGenerator).to receive(:new).and_return(generator)
|
70
|
+
expect(generator).to receive(:generate).with(subject.commit_history)
|
71
|
+
subject.generate_output
|
72
|
+
end
|
73
|
+
|
74
|
+
it "lists the repositories" do
|
75
|
+
lister = RepositoryLister.new
|
76
|
+
expect(RepositoryLister).to receive(:new).and_return(lister)
|
77
|
+
expect(lister).to receive(:list).with(subject.commit_history)
|
78
|
+
subject.list_committed_repositories
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
@@ -0,0 +1,202 @@
|
|
1
|
+
|
2
|
+
describe "CodepicuousConfigurator reads all the config files and provides the data needed for running Codespicuous" do
|
3
|
+
|
4
|
+
subject { CodespicuousConfigurator.new(CodespicuousConfig.new) }
|
5
|
+
|
6
|
+
it "Should process the yaml file" do
|
7
|
+
expect(subject).to receive(:parse_command_line_arguments).with(["argv"])
|
8
|
+
expect(subject).to receive(:configure_from_yaml)
|
9
|
+
expect(subject).to receive(:postprocess_yaml_configuration)
|
10
|
+
expect(subject).to receive(:find_alternative_configuration_files)
|
11
|
+
expect(subject).to receive(:validate_configuration)
|
12
|
+
subject.configure(["argv"])
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should be able to handle the -r command line option" do
|
16
|
+
subject.parse_command_line_arguments(["-r"])
|
17
|
+
expect(subject.config.list_repositories).to be true
|
18
|
+
end
|
19
|
+
|
20
|
+
it "Should be able to handle the -i command line option for input directory " do
|
21
|
+
subject.parse_command_line_arguments(["-i", "blah"])
|
22
|
+
expect(subject.config.input_path).to eq Pathname.new("blah")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "Should be able to handle the -o command line option for output directory " do
|
26
|
+
subject.parse_command_line_arguments(["-o", "blah"])
|
27
|
+
expect(subject.config.output_path).to eq Pathname.new("blah")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "Should post process the YAML file" do
|
31
|
+
yaml_content = {}
|
32
|
+
|
33
|
+
expect(subject).to receive(:postprocess_yaml_configuration_repositories).with(yaml_content)
|
34
|
+
expect(subject).to receive(:postprocess_yaml_configuration_committers).with(yaml_content)
|
35
|
+
|
36
|
+
subject.postprocess_yaml_configuration(yaml_content)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "Should find alternative config files" do
|
40
|
+
expect(subject).to receive(:find_alternative_configuration_files_for_repositories)
|
41
|
+
expect(subject).to receive(:find_alternative_configuration_files_for_committers)
|
42
|
+
|
43
|
+
subject.find_alternative_configuration_files
|
44
|
+
end
|
45
|
+
|
46
|
+
context "Read the YAML file" do
|
47
|
+
|
48
|
+
it "reads the codespicuous configuration from YAML file when the file exists" do
|
49
|
+
expect(File).to receive(:exist?).with("codespicuous.yaml").and_return(true)
|
50
|
+
expect(File).to receive(:read).with("codespicuous.yaml").and_return("offline: true")
|
51
|
+
expect(subject).to receive(:puts).with('** Configuring options with "codespicuous.yaml"')
|
52
|
+
|
53
|
+
subject.configure_from_yaml
|
54
|
+
expect(subject.config.offline).to eq true
|
55
|
+
end
|
56
|
+
|
57
|
+
it "Ignores the missing options file and tries to use defaults" do
|
58
|
+
expect(File).to receive(:exist?).with("codespicuous.yaml").and_return(false)
|
59
|
+
|
60
|
+
subject.configure_from_yaml
|
61
|
+
|
62
|
+
expect(subject.config.offline).to eq false
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "Parsing the repositories" do
|
67
|
+
|
68
|
+
it "Processes the repositories out of the options with all selected" do
|
69
|
+
|
70
|
+
yaml_content = {"repositories" => { "name" => "url"}}
|
71
|
+
|
72
|
+
subject.postprocess_yaml_configuration_repositories(yaml_content)
|
73
|
+
|
74
|
+
repositories = Repositories.new
|
75
|
+
repositories.add(Repository.new("name", "url"))
|
76
|
+
|
77
|
+
expect(subject.repositories).to eq repositories
|
78
|
+
expect(subject.repositories_to_check).to eq repositories
|
79
|
+
end
|
80
|
+
|
81
|
+
it "Processes the repositories out of the options, with only the selected one" do
|
82
|
+
|
83
|
+
yaml_content = {"repositories" => { "name" => "url", "name2" => "url2"},
|
84
|
+
"repositories_to_check" => ["name2"]}
|
85
|
+
|
86
|
+
subject.postprocess_yaml_configuration_repositories(yaml_content)
|
87
|
+
|
88
|
+
repositories = Repositories.new
|
89
|
+
repositories.add(Repository.new("name", "url"))
|
90
|
+
repositories.add(Repository.new("name2", "url2"))
|
91
|
+
|
92
|
+
checked_repositories = Repositories.new
|
93
|
+
checked_repositories.add(Repository.new("name2", "url2"))
|
94
|
+
|
95
|
+
expect(subject.repositories).to eq repositories
|
96
|
+
expect(subject.repositories_to_check).to eq checked_repositories
|
97
|
+
end
|
98
|
+
|
99
|
+
it "will not bother checking the CSV file when it found repositories already" do
|
100
|
+
repositories = Repositories.new
|
101
|
+
repositories.add(Repository.new("name", "url"))
|
102
|
+
expect(subject).to receive(:repositories).and_return(repositories)
|
103
|
+
expect(File).not_to receive(:exist?)
|
104
|
+
|
105
|
+
subject.find_alternative_configuration_files_for_repositories
|
106
|
+
end
|
107
|
+
|
108
|
+
it "will check whether there is a CSV file and continue if not found" do
|
109
|
+
expect(File).to receive(:exist?).with("repositories.csv").and_return(false)
|
110
|
+
|
111
|
+
subject.find_alternative_configuration_files_for_repositories
|
112
|
+
|
113
|
+
expect(subject.repositories).to eq Repositories.new
|
114
|
+
end
|
115
|
+
|
116
|
+
it "will read the CSV file when it exists" do
|
117
|
+
expect(File).to receive(:exist?).with("repositories.csv").and_return(true)
|
118
|
+
expect(File).to receive(:read).with("repositories.csv").and_return("name,url\nrepos,https://repos.com")
|
119
|
+
expect(subject).to receive(:puts).with('** Configuring repositories with "repositories.csv"')
|
120
|
+
|
121
|
+
subject.find_alternative_configuration_files_for_repositories
|
122
|
+
|
123
|
+
repositories = Repositories.new
|
124
|
+
repositories.add(Repository.new("repos", "https://repos.com"))
|
125
|
+
|
126
|
+
expect(subject.repositories).to eq repositories
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context "Parsing the teams and committers" do
|
131
|
+
|
132
|
+
before (:each) do
|
133
|
+
@team_wine = Team.new("Wine")
|
134
|
+
@committer_bas = Committer.create_committer("basvodde", "Bas", "Vodde", "basv@wow.com", @team_wine)
|
135
|
+
end
|
136
|
+
|
137
|
+
it "can have no committers and teams. Just empty then" do
|
138
|
+
subject.postprocess_yaml_configuration_committers({})
|
139
|
+
|
140
|
+
expect(subject.committers).to eq Committers.new
|
141
|
+
expect(subject.teams).to eq Teams.new
|
142
|
+
end
|
143
|
+
|
144
|
+
it "can get the team info from the yaml file" do
|
145
|
+
|
146
|
+
yaml_content = {"teams" =>
|
147
|
+
{"Wine" => [{
|
148
|
+
"First Name" => "Bas",
|
149
|
+
"Last Name" => "Vodde",
|
150
|
+
"Email" => "basv@wow.com",
|
151
|
+
"Login" => "basvodde" } ]
|
152
|
+
} }
|
153
|
+
|
154
|
+
subject.postprocess_yaml_configuration_committers(yaml_content)
|
155
|
+
|
156
|
+
committers = Committers.new
|
157
|
+
@team_wine.add_member(@committer_bas)
|
158
|
+
committers.add(@committer_bas)
|
159
|
+
|
160
|
+
teams = Teams.new
|
161
|
+
teams.add(@team_wine)
|
162
|
+
|
163
|
+
expect(subject.committers).to eq committers
|
164
|
+
expect(subject.teams).to eq teams
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
it "will not bother checking the CSV file when it found committers already" do
|
169
|
+
committers = Committers.new
|
170
|
+
committers.add(@committer_bas)
|
171
|
+
expect(subject).to receive(:committers).and_return(committers)
|
172
|
+
expect(File).not_to receive(:exist?)
|
173
|
+
|
174
|
+
subject.find_alternative_configuration_files_for_committers
|
175
|
+
end
|
176
|
+
|
177
|
+
it "will check whether there is a CSV file and continue if not found" do
|
178
|
+
expect(File).to receive(:exist?).with("committers.csv").and_return(false)
|
179
|
+
|
180
|
+
subject.find_alternative_configuration_files_for_committers
|
181
|
+
|
182
|
+
expect(subject.committers).to eq Committers.new
|
183
|
+
end
|
184
|
+
|
185
|
+
it "will read the CSV file when it exists" do
|
186
|
+
expect(File).to receive(:exist?).with("committers.csv").and_return(true)
|
187
|
+
expect(File).to receive(:read).with("committers.csv").and_return("#,First Name,Last Name,Email,Login,Team,Specialization,Manager,day1,day2,day3,Comments,Present,Questionaire send,Answered,Pretest,Dietary,Commits,Blamed lines,Average LOC/Commit
|
188
|
+
#1,Bas,Vodde,basv@wow.com,basvodde,Wine")
|
189
|
+
expect(subject).to receive(:puts).with('** Configuring committers with "committers.csv"')
|
190
|
+
|
191
|
+
subject.find_alternative_configuration_files_for_committers
|
192
|
+
|
193
|
+
committers = Committers.new
|
194
|
+
committers.add(@committer_bas)
|
195
|
+
|
196
|
+
expect(subject.committers).to eq committers
|
197
|
+
end
|
198
|
+
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|