dragnet 5.2.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/.github/workflows/release.yml +45 -0
- data/.github/workflows/ruby-linters.yml +41 -0
- data/.github/workflows/ruby-tests.yml +38 -0
- data/.github/workflows/sphinx-doc.yml +79 -0
- data/.gitignore +13 -0
- data/.reek.yml +15 -0
- data/.rspec +3 -0
- data/.rubocop.yml +14 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +178 -0
- data/Gemfile +18 -0
- data/README.md +119 -0
- data/Rakefile +8 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/default.reek +7 -0
- data/dragnet.gemspec +39 -0
- data/exe/dragnet +9 -0
- data/lib/dragnet/base_repository.rb +69 -0
- data/lib/dragnet/cli/base.rb +72 -0
- data/lib/dragnet/cli/logger.rb +72 -0
- data/lib/dragnet/cli/master.rb +173 -0
- data/lib/dragnet/cli.rb +8 -0
- data/lib/dragnet/errors/error.rb +8 -0
- data/lib/dragnet/errors/file_not_found_error.rb +11 -0
- data/lib/dragnet/errors/incompatible_repository_error.rb +10 -0
- data/lib/dragnet/errors/missing_timestamp_attribute_error.rb +11 -0
- data/lib/dragnet/errors/no_mtr_files_found_error.rb +11 -0
- data/lib/dragnet/errors/not_a_repository_error.rb +11 -0
- data/lib/dragnet/errors/repo_path_not_found_error.rb +10 -0
- data/lib/dragnet/errors/unable_to_write_report_error.rb +11 -0
- data/lib/dragnet/errors/unknown_export_format_error.rb +11 -0
- data/lib/dragnet/errors/validation_error.rb +11 -0
- data/lib/dragnet/errors/yaml_format_error.rb +9 -0
- data/lib/dragnet/errors.rb +9 -0
- data/lib/dragnet/explorer.rb +103 -0
- data/lib/dragnet/exporter.rb +130 -0
- data/lib/dragnet/exporters/exporter.rb +29 -0
- data/lib/dragnet/exporters/html_exporter.rb +158 -0
- data/lib/dragnet/exporters/id_generator.rb +35 -0
- data/lib/dragnet/exporters/json_exporter.rb +34 -0
- data/lib/dragnet/exporters/serializers/repo_serializer.rb +40 -0
- data/lib/dragnet/exporters/serializers/test_record_serializer.rb +101 -0
- data/lib/dragnet/exporters/serializers/verification_result_serializer.rb +34 -0
- data/lib/dragnet/exporters/serializers.rb +12 -0
- data/lib/dragnet/exporters/templates/template.html.erb +518 -0
- data/lib/dragnet/exporters.rb +13 -0
- data/lib/dragnet/helpers/repository_helper.rb +27 -0
- data/lib/dragnet/multi_repository.rb +48 -0
- data/lib/dragnet/repo.rb +31 -0
- data/lib/dragnet/repository.rb +77 -0
- data/lib/dragnet/test_record.rb +91 -0
- data/lib/dragnet/validator.rb +79 -0
- data/lib/dragnet/validators/data_validator.rb +75 -0
- data/lib/dragnet/validators/entities/repo_validator.rb +31 -0
- data/lib/dragnet/validators/entities/test_record_validator.rb +93 -0
- data/lib/dragnet/validators/entities.rb +12 -0
- data/lib/dragnet/validators/fields/description_validator.rb +24 -0
- data/lib/dragnet/validators/fields/field_validator.rb +69 -0
- data/lib/dragnet/validators/fields/files_validator.rb +29 -0
- data/lib/dragnet/validators/fields/id_validator.rb +36 -0
- data/lib/dragnet/validators/fields/meta_data_field_validator.rb +36 -0
- data/lib/dragnet/validators/fields/path_validator.rb +22 -0
- data/lib/dragnet/validators/fields/repos_validator.rb +62 -0
- data/lib/dragnet/validators/fields/result_validator.rb +33 -0
- data/lib/dragnet/validators/fields/sha1_validator.rb +42 -0
- data/lib/dragnet/validators/fields.rb +17 -0
- data/lib/dragnet/validators/files_validator.rb +85 -0
- data/lib/dragnet/validators/repos_validator.rb +74 -0
- data/lib/dragnet/validators/validator.rb +20 -0
- data/lib/dragnet/validators.rb +12 -0
- data/lib/dragnet/verification_result.rb +125 -0
- data/lib/dragnet/verifier.rb +64 -0
- data/lib/dragnet/verifiers/changes_verifier.rb +70 -0
- data/lib/dragnet/verifiers/files_verifier.rb +51 -0
- data/lib/dragnet/verifiers/repos_verifier.rb +92 -0
- data/lib/dragnet/verifiers/repository_verifier.rb +27 -0
- data/lib/dragnet/verifiers/result_verifier.rb +32 -0
- data/lib/dragnet/verifiers/test_record_verifier.rb +85 -0
- data/lib/dragnet/verifiers/verifier.rb +37 -0
- data/lib/dragnet/verifiers.rb +8 -0
- data/lib/dragnet/version.rb +5 -0
- data/lib/dragnet.rb +18 -0
- metadata +190 -0
@@ -0,0 +1,130 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'errors/unable_to_write_report_error'
|
4
|
+
require_relative 'errors/unknown_export_format_error'
|
5
|
+
require_relative 'exporters/html_exporter'
|
6
|
+
require_relative 'exporters/json_exporter'
|
7
|
+
|
8
|
+
module Dragnet
|
9
|
+
# The base exporter class, receives an array of test records, an array of
|
10
|
+
# errors and an array of file names and exports the results to the given
|
11
|
+
# files. (For each file the format is deduced from its file name).
|
12
|
+
class Exporter
|
13
|
+
KNOWN_FORMATS = {
|
14
|
+
'HTML' => { extensions: %w[.html .htm], exporter: Dragnet::Exporters::HTMLExporter },
|
15
|
+
'JSON' => { extensions: %w[.json], exporter: Dragnet::Exporters::JSONExporter }
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
attr_reader :test_records, :errors, :repository, :targets, :logger
|
19
|
+
|
20
|
+
# Creates a new instance of the class.
|
21
|
+
# @param [Array<Dragnet::TestRecord>] test_records The array of MTRs that
|
22
|
+
# should be included in the reports.
|
23
|
+
# @param [Array<Hash>] errors An array of Hashes with the data of the MTR
|
24
|
+
# files that did not pass the validation process.
|
25
|
+
# @param [Dragnet::Repository, Dragnet::MultiRepository] repository The
|
26
|
+
# repository where the MTR files and the source code are stored.
|
27
|
+
# @param [Array<String>] targets The array of target files. For each of them
|
28
|
+
# the format of the export will be deduced from the file's extension.
|
29
|
+
# @param [#info, #debug] logger A logger object to use for output.
|
30
|
+
def initialize(test_records:, errors:, repository:, targets:, logger:)
|
31
|
+
@test_records = test_records
|
32
|
+
@errors = errors
|
33
|
+
@repository = repository
|
34
|
+
@targets = targets
|
35
|
+
@logger = logger
|
36
|
+
end
|
37
|
+
|
38
|
+
# Starts the export process.
|
39
|
+
# @raise [Dragnet::Errors::UnableToWriteReportError] If one of the target
|
40
|
+
# files cannot be created, opened, or if the output cannot be written to
|
41
|
+
# it.
|
42
|
+
def export
|
43
|
+
logger.info 'Starting export process...'
|
44
|
+
log_target_files
|
45
|
+
|
46
|
+
formats.each do |format, targets|
|
47
|
+
exporter = KNOWN_FORMATS.dig(format, :exporter).new(
|
48
|
+
test_records: test_records, errors: errors, repository: repository, logger: logger
|
49
|
+
)
|
50
|
+
|
51
|
+
text = exporter.export
|
52
|
+
write_output(text, format, targets)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
# Writes the given text output with the given format to the given targets.
|
59
|
+
# @param [String] text The text output to write.
|
60
|
+
# @param [String] format The format of the target file.
|
61
|
+
# @param [Array<String>] targets The paths of the target files the output
|
62
|
+
# should be written to.
|
63
|
+
# @raise [Dragnet::Errors::UnableToWriteReportError] If one of the target
|
64
|
+
# files cannot be created, opened, or if the output cannot be written to
|
65
|
+
# it.
|
66
|
+
def write_output(text, format, targets)
|
67
|
+
targets.each do |target|
|
68
|
+
logger.info "Writing #{format} output to #{target}..."
|
69
|
+
|
70
|
+
begin
|
71
|
+
start = Time.now
|
72
|
+
bytes = File.write(target, text)
|
73
|
+
elapsed = Time.now - start
|
74
|
+
|
75
|
+
logger.debug("Ok (#{bytes} bytes written in #{elapsed} seconds)")
|
76
|
+
rescue SystemCallError => e
|
77
|
+
raise Dragnet::Errors::UnableToWriteReportError,
|
78
|
+
"Unable to write report output to #{target}: #{e.message}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Writes a log entry with the files that will be written as a result of the
|
84
|
+
# export process (each with its corresponding format).
|
85
|
+
def log_target_files
|
86
|
+
files_with_formats = formats.flat_map do |format, targets|
|
87
|
+
targets.map { |target| "\t * #{target} as #{format}" }
|
88
|
+
end
|
89
|
+
|
90
|
+
logger.debug "Target files are:\n#{files_with_formats.join("\n")}"
|
91
|
+
end
|
92
|
+
|
93
|
+
# @return [Hash] A hash whose keys are known formats and whose values are
|
94
|
+
# arrays of target files.
|
95
|
+
def formats
|
96
|
+
@formats ||= deduce_formats
|
97
|
+
end
|
98
|
+
|
99
|
+
# Deduces the format of each target file (given its extension) and relates
|
100
|
+
# them to their corresponding formats.
|
101
|
+
# @return [Hash] A hash whose keys are known formats and whose values are
|
102
|
+
# arrays of target files.
|
103
|
+
def deduce_formats
|
104
|
+
formats = {}
|
105
|
+
|
106
|
+
targets.each do |target|
|
107
|
+
extension = File.extname(target).downcase
|
108
|
+
format, = KNOWN_FORMATS.find { |_name, config| config[:extensions].include?(extension) }
|
109
|
+
unknown_format_error(extension) unless format
|
110
|
+
|
111
|
+
formats[format] ||= []
|
112
|
+
formats[format] << target
|
113
|
+
end
|
114
|
+
|
115
|
+
formats
|
116
|
+
end
|
117
|
+
|
118
|
+
# Raises a +Dragnet::Errors::UnknownExportFormatError+ with the proper error
|
119
|
+
# message.
|
120
|
+
# @param [String] extension The extension of the given target file.
|
121
|
+
# @raise [Dragnet::Errors::UnknownExportFormatError] is always raised.
|
122
|
+
def unknown_format_error(extension)
|
123
|
+
allowed_extensions = KNOWN_FORMATS.flat_map { |_format, config| config[:extensions] }
|
124
|
+
|
125
|
+
raise Dragnet::Errors::UnknownExportFormatError,
|
126
|
+
"Unknown export format: '#{extension}'. Valid export formats are: "\
|
127
|
+
"#{allowed_extensions.join(', ')}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dragnet
|
4
|
+
module Exporters
|
5
|
+
# Base class for all exporter classes.
|
6
|
+
class Exporter
|
7
|
+
attr_reader :test_records, :errors, :repository, :logger
|
8
|
+
|
9
|
+
# @param [Array<Hash>] test_records The array of test records.
|
10
|
+
# @param [Array<Hash>] errors The array of errors.
|
11
|
+
# @param [Dragnet::Repository, Dragnet::MultiRepository] repository The
|
12
|
+
# repository where the MTR files and the source code are stored.
|
13
|
+
# @param [#info] logger A logger object to use for output.
|
14
|
+
def initialize(test_records:, errors:, repository:, logger:)
|
15
|
+
@test_records = test_records
|
16
|
+
@errors = errors
|
17
|
+
@repository = repository
|
18
|
+
@logger = logger
|
19
|
+
end
|
20
|
+
|
21
|
+
# @raise [NotImplementedError] Is always raised. Subclasses are expected
|
22
|
+
# to override this method.
|
23
|
+
def export
|
24
|
+
raise NotImplementedError,
|
25
|
+
"'export' method not implemented for class #{self.class}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
require_relative '../helpers/repository_helper'
|
6
|
+
require_relative 'exporter'
|
7
|
+
|
8
|
+
module Dragnet
|
9
|
+
module Exporters
|
10
|
+
# Creates an HTML report from the given Test Records and Errors data.
|
11
|
+
class HTMLExporter < Dragnet::Exporters::Exporter
|
12
|
+
include Dragnet::Helpers::RepositoryHelper
|
13
|
+
|
14
|
+
TEMPLATE = File.join(__dir__, 'templates', 'template.html.erb').freeze
|
15
|
+
|
16
|
+
# Generates the report and returns it as a string.
|
17
|
+
# @return [String] The generated HTML report.
|
18
|
+
def export
|
19
|
+
logger.info "Generating HTML report from template: #{TEMPLATE}..."
|
20
|
+
ERB.new(File.read(TEMPLATE)).result(binding)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# Returns the percentage that +num1+ represents with respect to +num2+
|
26
|
+
# @param [Integer, Float] num1 A number.
|
27
|
+
# @param [Integer, Float] num2 A number.
|
28
|
+
# @return [Integer, Float] The percentage that +num1+ represents with
|
29
|
+
# respect to +num2+ rounded to two decimal places.
|
30
|
+
def percentage(num1, num2)
|
31
|
+
return 0.0 if num1.zero? || num2.zero?
|
32
|
+
|
33
|
+
((num1.to_f / num2) * 100).round(2)
|
34
|
+
end
|
35
|
+
|
36
|
+
# @param [Dragnet::Repository] repository The repository whose branches
|
37
|
+
# should be retrieved.
|
38
|
+
# @return [Array<String>] An array with the names of the branches that
|
39
|
+
# "contain" the current head of the repository (may be empty).
|
40
|
+
def software_branches(repository)
|
41
|
+
# (uniq needed because of remote/local branches)
|
42
|
+
repository.branches_with_head.map(&:name).uniq
|
43
|
+
rescue Git::GitExecuteError => e
|
44
|
+
logger.warn "Failed to read branches information from the repository at #{repository.path}"
|
45
|
+
logger.warn e.message
|
46
|
+
[]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Method used to memoize the output of the +group_by_requirement+ method.
|
50
|
+
# @see #group_by_requirement
|
51
|
+
# @return [Hash] A hash whose keys are the requirement IDs and whose
|
52
|
+
# values are arrays of MTRs
|
53
|
+
def test_records_by_requirement
|
54
|
+
@test_records_by_requirement ||= group_by_requirement
|
55
|
+
end
|
56
|
+
|
57
|
+
# Groups the MTRs by the requirement(s) they are covering, if a MTR covers
|
58
|
+
# more than one requirement it will be added to all of them, if a
|
59
|
+
# requirement is covered by more than one MTR the requirement will end up
|
60
|
+
# with more than one MTR, example:
|
61
|
+
#
|
62
|
+
# {
|
63
|
+
# 'ESR_REQ_9675' => [MTR1],
|
64
|
+
# 'ESR_REQ_1879' => [MTR2, MTR3]
|
65
|
+
# 'ESR_REQ_4714' => [MTR3]
|
66
|
+
# }
|
67
|
+
#
|
68
|
+
# @return [Hash] A hash whose keys are the requirement IDs and whose
|
69
|
+
# values are arrays of MTRs
|
70
|
+
def group_by_requirement
|
71
|
+
tests_by_requirement = {}
|
72
|
+
|
73
|
+
test_records.each do |test_record|
|
74
|
+
ids = *test_record.id
|
75
|
+
ids.each do |id|
|
76
|
+
tests_by_requirement[id] ||= []
|
77
|
+
tests_by_requirement[id] << test_record
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
tests_by_requirement
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns the HTML code needed to render the Review Status of a MTR as a
|
85
|
+
# badge.
|
86
|
+
# @param [Dragnet::TestRecord] test_record The Test Record.
|
87
|
+
# @return [String] The HTML code to display the Test Record's review
|
88
|
+
# status as a badge.
|
89
|
+
def review_status_badge(test_record)
|
90
|
+
if test_record.review_status
|
91
|
+
color = test_record.reviewed? ? 'green' : 'red'
|
92
|
+
review_status = test_record.review_status.capitalize
|
93
|
+
else
|
94
|
+
color = 'gray'
|
95
|
+
review_status = '(unknown)'
|
96
|
+
end
|
97
|
+
|
98
|
+
badge_html(color, review_status)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Returns the HTML code needed to display the verification result of a MTR
|
102
|
+
# (the color and the text inside the badge are picked in accordance to the
|
103
|
+
# given result).
|
104
|
+
# @param [Dragnet::VerificationResult] verification_result The result of
|
105
|
+
# the verification for a given +TestRecord+
|
106
|
+
# @return [String] The HTML code needed to display the result as a badge.
|
107
|
+
def verification_result_badge(verification_result)
|
108
|
+
badge_html(
|
109
|
+
verification_result_color(verification_result),
|
110
|
+
verification_result.status.capitalize
|
111
|
+
)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Returns a color that depends on the verification result for a Test
|
115
|
+
# Record. To be used on HTML elements.
|
116
|
+
# @param [Dragnet::VerificationResult] verification_result The
|
117
|
+
# +VerificationResult+ object.
|
118
|
+
# @return [String] The corresponding color (depends on the +status+ field
|
119
|
+
# of the +VerificationResult+ object).
|
120
|
+
def verification_result_color(verification_result)
|
121
|
+
case verification_result.status
|
122
|
+
when :passed
|
123
|
+
'green'
|
124
|
+
when :skipped
|
125
|
+
'yellow'
|
126
|
+
else
|
127
|
+
'red'
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Returns the color that should be used for the highlight line on the left
|
132
|
+
# of the card given the result of the MTR's verification.
|
133
|
+
# @param [Dragnet::VerificationResult] verification_result The
|
134
|
+
# +VerificationResult+ object associated with the +TestRecord+ being
|
135
|
+
# rendered on the card.
|
136
|
+
def card_color(verification_result)
|
137
|
+
verification_result_color(verification_result)
|
138
|
+
end
|
139
|
+
|
140
|
+
# Returns the HTML string to produce a Badge
|
141
|
+
# @param [String] color The color of the badge.
|
142
|
+
# @param [String] text The text that goes inside the badge.
|
143
|
+
# @return [String] The HTML code to produce a badge with the given color
|
144
|
+
# and text.
|
145
|
+
def badge_html(color, text)
|
146
|
+
"<span class=\"badge bg-#{color}\">#{text}</span>"
|
147
|
+
end
|
148
|
+
|
149
|
+
# Converts the ID (+String+) or IDs (+Array<String>+) of a +TestRecord+
|
150
|
+
# object into a string that can be safely rendered in the HTML report.
|
151
|
+
# @param [Dragnet::TestRecord] test_record The +TestRecord+ object.
|
152
|
+
# @return [String] A string with the ID or IDs of the +TestRecord+ object.
|
153
|
+
def test_record_id_to_string(test_record)
|
154
|
+
Array(test_record.id).join(', ')
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'digest'
|
4
|
+
|
5
|
+
require_relative '../helpers/repository_helper'
|
6
|
+
|
7
|
+
module Dragnet
|
8
|
+
module Exporters
|
9
|
+
# Generates unique IDs for the Manual Test Records by hashing some of their
|
10
|
+
# properties into a hexadecimal SHA1.
|
11
|
+
class IDGenerator
|
12
|
+
include Dragnet::Helpers::RepositoryHelper
|
13
|
+
|
14
|
+
attr_reader :repository
|
15
|
+
|
16
|
+
# @param [Dragnet::Repository] repository The repository where the MTR
|
17
|
+
# files are located. This allows the SHA1 to be calculated with relative
|
18
|
+
# paths to the MTRs' files.
|
19
|
+
def initialize(repository)
|
20
|
+
@repository = repository
|
21
|
+
end
|
22
|
+
|
23
|
+
# Calculates the ID of the given MTR
|
24
|
+
# @param [Dragnet::TestRecord] test_record The record for which the ID
|
25
|
+
# should be calculated.
|
26
|
+
# @return [String] The ID for the given +TestRecord+.
|
27
|
+
# :reek:FeatureEnvy (Cannot be done in the TestRecord itself because it needs the Repository)
|
28
|
+
def id_for(test_record)
|
29
|
+
string = "#{relative_to_repo(test_record.source_file)}#{test_record.id}"
|
30
|
+
# noinspection RubyMismatchedReturnType (This is never nil)
|
31
|
+
Digest::SHA1.hexdigest(string)[0...16]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
require_relative 'exporter'
|
6
|
+
require_relative 'id_generator'
|
7
|
+
require_relative 'serializers/test_record_serializer'
|
8
|
+
|
9
|
+
module Dragnet
|
10
|
+
module Exporters
|
11
|
+
# Exports the results for the Manual Test Record verification to a JSON
|
12
|
+
# string.
|
13
|
+
class JSONExporter < ::Dragnet::Exporters::Exporter
|
14
|
+
# @return [String] A JSON string containing an array of objects, one for
|
15
|
+
# each Test Record.
|
16
|
+
def export
|
17
|
+
logger.info 'Exporting data to JSON'
|
18
|
+
test_records.map do |test_record|
|
19
|
+
::Dragnet::Exporters::Serializers::TestRecordSerializer
|
20
|
+
.new(test_record, repository).serialize
|
21
|
+
.merge(id: id_generator.id_for(test_record))
|
22
|
+
end.to_json
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# @return [Dragnet::Exporters::IDGenerator] An instance of the IDGenerator
|
28
|
+
# class that can be used to calculate the ID for the exported MTRs.
|
29
|
+
def id_generator
|
30
|
+
@id_generator ||= ::Dragnet::Exporters::IDGenerator.new(repository)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
require 'active_support/core_ext/object/blank'
|
5
|
+
|
6
|
+
module Dragnet
|
7
|
+
module Exporters
|
8
|
+
module Serializers
|
9
|
+
# Serializes a +Repo+ object into a +Hash+
|
10
|
+
class RepoSerializer
|
11
|
+
attr_reader :repo
|
12
|
+
|
13
|
+
# @param [Dragnet::Repo] repo The +Repo+ object to serialize.
|
14
|
+
def initialize(repo)
|
15
|
+
@repo = repo
|
16
|
+
end
|
17
|
+
|
18
|
+
# Serializes the given +Repo+ object.
|
19
|
+
# @return [Hash] A +Hash+ representing the given +Repo+ object.
|
20
|
+
def serialize
|
21
|
+
{
|
22
|
+
path: repo.path,
|
23
|
+
sha1: repo.sha1
|
24
|
+
}.tap do |hash|
|
25
|
+
hash[:files] = serialize_files if repo.files.present?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# Serializes the array of files attached to the +Repo+
|
32
|
+
# @return [Array<String>] The array of file names (without the path to
|
33
|
+
# the repository).
|
34
|
+
def serialize_files
|
35
|
+
repo.files.map { |file| file.to_s.gsub("#{repo.path}/", '') }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
require 'active_support/core_ext/object/blank'
|
5
|
+
|
6
|
+
require_relative '../../helpers/repository_helper'
|
7
|
+
require_relative 'repo_serializer'
|
8
|
+
require_relative 'verification_result_serializer'
|
9
|
+
|
10
|
+
module Dragnet
|
11
|
+
module Exporters
|
12
|
+
module Serializers
|
13
|
+
# Serializes a +TestRecord+ object into a +Hash+.
|
14
|
+
class TestRecordSerializer
|
15
|
+
include ::Dragnet::Helpers::RepositoryHelper
|
16
|
+
|
17
|
+
attr_reader :test_record, :repository
|
18
|
+
|
19
|
+
# @param [Dragnet::TestRecord] test_record The +TestRecord+ object to
|
20
|
+
# serialize.
|
21
|
+
# @param [Dragnet::RepositoryBase] repository The +Repository+ object
|
22
|
+
# associated with the +TestRecord+. Used to render file paths relative
|
23
|
+
# to the repository instead of as absolute paths.
|
24
|
+
def initialize(test_record, repository)
|
25
|
+
@test_record = test_record
|
26
|
+
@repository = repository
|
27
|
+
end
|
28
|
+
|
29
|
+
# rubocop:disable Metrics/AbcSize (because of the Hash)
|
30
|
+
# rubocop:disable Metrics/CyclomaticComplexity (because of the conditionals)
|
31
|
+
# rubocop:disable Metrics/PerceivedComplexity (because of the conditionals)
|
32
|
+
# rubocop:disable Metrics/MethodLength (because of he Hash)
|
33
|
+
|
34
|
+
# @return [Hash] A +Hash+ representing the given +TestRecord+ object.
|
35
|
+
def serialize
|
36
|
+
{
|
37
|
+
refs: Array(test_record.id),
|
38
|
+
result: test_record.result,
|
39
|
+
review_status: render_review_status,
|
40
|
+
verification_result: serialized_verification_result,
|
41
|
+
|
42
|
+
# TODO: Remove the started_at and finished_at attributes after solving
|
43
|
+
# https://esrlabs.atlassian.net/browse/JAY-493
|
44
|
+
started_at: serialized_verification_result[:started_at],
|
45
|
+
finished_at: serialized_verification_result[:finished_at]
|
46
|
+
}.tap do |hash|
|
47
|
+
hash[:sha1] = test_record.sha1 if test_record.sha1.present?
|
48
|
+
hash[:owner] = Array(test_record.name).join(', ') if test_record.name.present?
|
49
|
+
hash[:description] = test_record.description if test_record.description.present?
|
50
|
+
hash[:test_method] = Array(test_record.test_method) if test_record.test_method.present?
|
51
|
+
|
52
|
+
if test_record.tc_derivation_method.present?
|
53
|
+
hash[:tc_derivation_method] = Array(test_record.tc_derivation_method)
|
54
|
+
end
|
55
|
+
|
56
|
+
hash[:review_comments] = test_record.review_comments if test_record.review_comments.present?
|
57
|
+
hash[:findings] = test_record.findings if test_record.findings?
|
58
|
+
hash[:files] = serialize_files if test_record.files.present?
|
59
|
+
hash[:repos] = serialize_repos if test_record.repos.present?
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# rubocop:enable Metrics/AbcSize
|
64
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
65
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
66
|
+
# rubocop:enable Metrics/MethodLength
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
# Renders the +TestRecord+'s review status
|
71
|
+
# @return [String] The review status, either +'not_reviewed'+ or +'reviewed'+
|
72
|
+
def render_review_status
|
73
|
+
"#{test_record.reviewed? ? nil : 'not_'}reviewed"
|
74
|
+
end
|
75
|
+
|
76
|
+
# Serializes the files listed in the given +TestRecord+
|
77
|
+
# @return [Array<String>] An array of strings, one for each listed file.
|
78
|
+
def serialize_files
|
79
|
+
test_record.files.map { |file| relative_to_repo(file).to_s }
|
80
|
+
end
|
81
|
+
|
82
|
+
# Serializes the +Repo+ objects attached to the +TestRecord+
|
83
|
+
# @return [Array<Hash>] An array of +Hash+es representing each of the
|
84
|
+
# +Repo+ objects associated with the +TestRecord+
|
85
|
+
def serialize_repos
|
86
|
+
test_record.repos.map { |repo| ::Dragnet::Exporters::Serializers::RepoSerializer.new(repo).serialize }
|
87
|
+
end
|
88
|
+
|
89
|
+
# Serializes the +VerificationResult+ object attached to the given
|
90
|
+
# +TestRecord+
|
91
|
+
# @return [Hash] A +Hash+ representation of the +VerificationResult+
|
92
|
+
# object.
|
93
|
+
def serialized_verification_result
|
94
|
+
@serialized_verification_result ||= ::Dragnet::Exporters::Serializers::VerificationResultSerializer.new(
|
95
|
+
test_record.verification_result
|
96
|
+
).serialize
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dragnet
|
4
|
+
module Exporters
|
5
|
+
module Serializers
|
6
|
+
# Serializes a +VerificationResult+ object into a +Hash+.
|
7
|
+
class VerificationResultSerializer
|
8
|
+
attr_reader :verification_result
|
9
|
+
|
10
|
+
# Format used to serialize the +VerificationResult+'s date/time attributes.
|
11
|
+
DATE_FORMAT = '%F %T %z'
|
12
|
+
|
13
|
+
# @param [Dragnet::VerificationResult] verification_result The
|
14
|
+
# +VerificationResult+ object to serialize.
|
15
|
+
def initialize(verification_result)
|
16
|
+
@verification_result = verification_result
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Hash] The +Hash+ representation of the given
|
20
|
+
# +VerificationResult+ object.
|
21
|
+
def serialize
|
22
|
+
{
|
23
|
+
status: verification_result.status,
|
24
|
+
started_at: verification_result.started_at.strftime(DATE_FORMAT),
|
25
|
+
finished_at: verification_result.finished_at.strftime(DATE_FORMAT),
|
26
|
+
runtime: verification_result.runtime
|
27
|
+
}.tap do |hash|
|
28
|
+
hash[:reason] = verification_result.reason if verification_result.reason
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'serializers/repo_serializer'
|
4
|
+
require_relative 'serializers/test_record_serializer'
|
5
|
+
require_relative 'serializers/verification_result_serializer'
|
6
|
+
|
7
|
+
module Dragnet
|
8
|
+
module Exporters
|
9
|
+
# Namespace for the serializer classes used by the exporters.
|
10
|
+
module Serializers; end
|
11
|
+
end
|
12
|
+
end
|