Skip to content

Commit 7dcfd5f

Browse files
committed
Add --verbose flag
Previously, the tool alway provides output for every check it runs. This is not necessarily a bad thing because in `--format text` mode it provides a progress indicator, and in `--format json` mode it provides information on all the checks that are run under the current tool configuration. However, as the number of checks grows, the amount of output has become a bit overwhelming and may make it hard to find the information for the failed checks. So it makes sense to default to only showing information on the failed checks while providing the option to show all checks.
1 parent db86b5c commit 7dcfd5f

File tree

8 files changed

+113
-32
lines changed

8 files changed

+113
-32
lines changed

Diff for: check/check.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
"github.com/arduino/arduino-check/check/checkconfigurations"
2424
"github.com/arduino/arduino-check/check/checkdata"
25+
"github.com/arduino/arduino-check/check/checkresult"
2526
"github.com/arduino/arduino-check/configuration"
2627
"github.com/arduino/arduino-check/configuration/checkmode"
2728
"github.com/arduino/arduino-check/project"
@@ -49,11 +50,13 @@ func RunChecks(project project.Type) {
4950
}
5051

5152
// Output will be printed after all checks are finished when configured for "json" output format.
52-
feedback.Printf("Running check %s: ", checkConfiguration.ID)
53+
feedback.VerbosePrintf("Running check %s...\n", checkConfiguration.ID)
5354

5455
checkResult, checkOutput := checkConfiguration.CheckFunction()
5556
reportText := result.Results.Record(project, checkConfiguration, checkResult, checkOutput)
56-
feedback.Print(reportText)
57+
if (checkResult == checkresult.Fail) || configuration.Verbose() {
58+
feedback.Print(reportText)
59+
}
5760
}
5861

5962
// Checks are finished for this project, so summarize its check results in the report.

Diff for: cli/cli.go

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ func Root() *cobra.Command {
3737
rootCommand.PersistentFlags().String("project-type", "all", "Only check projects of the specified type and their subprojects. Can be {sketch|library|all}.")
3838
rootCommand.PersistentFlags().Bool("recursive", true, "Search path recursively for Arduino projects to check. Can be {true|false}.")
3939
rootCommand.PersistentFlags().String("report-file", "", "Save a report on the checks to this file.")
40+
rootCommand.PersistentFlags().BoolP("verbose", "v", false, "Show more information while running checks.")
4041
rootCommand.PersistentFlags().Bool("version", false, "Print version and timestamp of the build.")
4142

4243
return rootCommand

Diff for: configuration/configuration.go

+10
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ func Initialize(flags *pflag.FlagSet, projectPaths []string) error {
8585
reportFilePathString, _ := flags.GetString("report-file")
8686
reportFilePath = paths.New(reportFilePathString)
8787

88+
verbose, _ = flags.GetBool("verbose")
89+
8890
versionMode, _ = flags.GetBool("version")
8991

9092
targetPaths = nil
@@ -125,6 +127,7 @@ func Initialize(flags *pflag.FlagSet, projectPaths []string) error {
125127
"superproject type filter": SuperprojectTypeFilter(),
126128
"recursive": Recursive(),
127129
"report file": ReportFilePath(),
130+
"verbose": Verbose(),
128131
"projects path": TargetPaths(),
129132
}).Debug("Configuration initialized")
130133

@@ -178,6 +181,13 @@ func ReportFilePath() *paths.Path {
178181
return reportFilePath
179182
}
180183

184+
var verbose bool
185+
186+
// Verbose returns the verbosity setting.
187+
func Verbose() bool {
188+
return verbose
189+
}
190+
181191
var versionMode bool
182192

183193
func VersionMode() bool {

Diff for: configuration/configuration_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,18 @@ func TestInitializeVersion(t *testing.T) {
194194
assert.False(t, VersionMode())
195195
}
196196

197+
func TestInitializeVerbose(t *testing.T) {
198+
flags := test.ConfigurationFlags()
199+
200+
flags.Set("verbose", "true")
201+
assert.Nil(t, Initialize(flags, projectPaths))
202+
assert.True(t, Verbose())
203+
204+
flags.Set("verbose", "false")
205+
assert.Nil(t, Initialize(flags, projectPaths))
206+
assert.False(t, Verbose())
207+
}
208+
197209
func TestInitializeProjectPath(t *testing.T) {
198210
assert.Nil(t, Initialize(test.ConfigurationFlags(), []string{}))
199211
workingDirectoryPath, err := os.Getwd()

Diff for: result/feedback/feedback.go

+12
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ import (
2424
"github.com/sirupsen/logrus"
2525
)
2626

27+
// VerbosePrintf behaves like Printf but only prints when verbosity is enabled.
28+
func VerbosePrintf(format string, v ...interface{}) {
29+
VerbosePrint(fmt.Sprintf(format, v...))
30+
}
31+
32+
// VerbosePrint behaves like Print but only prints when verbosity is enabled.
33+
func VerbosePrint(message string) {
34+
if configuration.Verbose() && (configuration.OutputFormat() == outputformat.Text) {
35+
Printf(message)
36+
}
37+
}
38+
2739
// Printf behaves like fmt.Printf but only prints when output format is set to `text`.
2840
func Printf(format string, v ...interface{}) {
2941
Print(fmt.Sprintf(format, v...))

Diff for: result/result.go

+16-16
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func (results *Type) Record(checkedProject project.Type, checkConfiguration chec
9999
os.Exit(1)
100100
}
101101

102-
summaryText := fmt.Sprintf("%s\n", checkResult)
102+
summaryText := fmt.Sprintf("Check %s result: %s\n", checkConfiguration.ID, checkResult)
103103

104104
checkMessage := ""
105105
if checkLevel == checklevel.Error {
@@ -115,17 +115,6 @@ func (results *Type) Record(checkedProject project.Type, checkConfiguration chec
115115
summaryText += fmt.Sprintf("%s: %s\n", checkLevel, checkMessage)
116116
}
117117

118-
checkReport := checkReportType{
119-
Category: checkConfiguration.Category,
120-
Subcategory: checkConfiguration.Subcategory,
121-
ID: checkConfiguration.ID,
122-
Brief: checkConfiguration.Brief,
123-
Description: checkConfiguration.Description,
124-
Result: checkResult.String(),
125-
Level: checkLevel.String(),
126-
Message: checkMessage,
127-
}
128-
129118
reportExists, projectReportIndex := results.getProjectReportIndex(checkedProject.Path)
130119
if !reportExists {
131120
// There is no existing report for this project.
@@ -140,11 +129,22 @@ func (results *Type) Record(checkedProject project.Type, checkConfiguration chec
140129
LibraryManagerUpdate: configuration.CheckModes(checkedProject.ProjectType)[checkmode.LibraryManagerIndexed],
141130
Official: configuration.CheckModes(checkedProject.ProjectType)[checkmode.Official],
142131
},
143-
Checks: []checkReportType{checkReport},
132+
Checks: []checkReportType{},
144133
},
145134
)
146-
} else {
147-
// There's already a report for this project; just add the checks report to it.
135+
}
136+
137+
if (checkResult == checkresult.Fail) || configuration.Verbose() {
138+
checkReport := checkReportType{
139+
Category: checkConfiguration.Category,
140+
Subcategory: checkConfiguration.Subcategory,
141+
ID: checkConfiguration.ID,
142+
Brief: checkConfiguration.Brief,
143+
Description: checkConfiguration.Description,
144+
Result: checkResult.String(),
145+
Level: checkLevel.String(),
146+
Message: checkMessage,
147+
}
148148
results.Projects[projectReportIndex].Checks = append(results.Projects[projectReportIndex].Checks, checkReport)
149149
}
150150

@@ -266,7 +266,7 @@ func (results Type) getProjectReportIndex(projectPath *paths.Path) (bool, int) {
266266
}
267267

268268
// There is no element in the report for this project.
269-
return false, index + 1
269+
return false, len(results.Projects)
270270
}
271271

272272
// message fills the message template provided by the check configuration with the check output.

Diff for: result/result_test.go

+56-14
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ import (
3434
"github.com/stretchr/testify/require"
3535
)
3636

37+
var projectPaths []string
38+
39+
func init() {
40+
projectPath, err := os.Getwd() // Path to an arbitrary folder that is guaranteed to exist.
41+
if err != nil {
42+
panic(err)
43+
}
44+
projectPaths = []string{projectPath}
45+
}
46+
3747
func TestInitialize(t *testing.T) {
3848
flags := test.ConfigurationFlags()
3949
flags.Set("project-type", "sketch")
@@ -52,24 +62,29 @@ func TestInitialize(t *testing.T) {
5262
}
5363

5464
func TestRecord(t *testing.T) {
65+
flags := test.ConfigurationFlags()
66+
require.Nil(t, configuration.Initialize(flags, projectPaths))
67+
5568
checkedProject := project.Type{
5669
Path: paths.New("/foo/bar"),
5770
ProjectType: projecttype.Sketch,
5871
SuperprojectType: projecttype.Library,
5972
}
6073

6174
var results Type
75+
results.Initialize()
6276
checkConfiguration := checkconfigurations.Configurations()[0]
6377
checkOutput := "foo"
6478
summaryText := results.Record(checkedProject, checkConfiguration, checkresult.Fail, checkOutput)
65-
assert.Equal(t, fmt.Sprintf("%s\n%s: %s\n", checkresult.Fail, checklevel.Error, message(checkConfiguration.MessageTemplate, checkOutput)), summaryText)
79+
assert.Equal(t, fmt.Sprintf("Check %s result: %s\n%s: %s\n", checkConfiguration.ID, checkresult.Fail, checklevel.Error, message(checkConfiguration.MessageTemplate, checkOutput)), summaryText)
6680
summaryText = results.Record(checkedProject, checkConfiguration, checkresult.NotRun, checkOutput)
67-
assert.Equal(t, fmt.Sprintf("%s\n%s: %s\n", checkresult.NotRun, checklevel.Notice, checkOutput), summaryText, "Non-fail result should not use message")
81+
assert.Equal(t, fmt.Sprintf("Check %s result: %s\n%s: %s\n", checkConfiguration.ID, checkresult.NotRun, checklevel.Notice, checkOutput), summaryText, "Non-fail result should not use message")
6882
summaryText = results.Record(checkedProject, checkConfiguration, checkresult.Pass, "")
6983
assert.Equal(t, "", "", summaryText, "Non-failure result with no check function output should result in an empty summary")
7084

85+
flags.Set("verbose", "true")
86+
require.Nil(t, configuration.Initialize(flags, projectPaths))
7187
checkResult := checkresult.Pass
72-
7388
results.Initialize()
7489
results.Record(checkedProject, checkConfiguration, checkResult, checkOutput)
7590
projectReport := results.Projects[0]
@@ -80,7 +95,7 @@ func TestRecord(t *testing.T) {
8095
assert.Equal(t, configuration.CheckModes(checkedProject.ProjectType)[checkmode.LibraryManagerSubmission], projectConfigurationReport.LibraryManagerSubmit)
8196
assert.Equal(t, configuration.CheckModes(checkedProject.ProjectType)[checkmode.LibraryManagerIndexed], projectConfigurationReport.LibraryManagerUpdate)
8297
assert.Equal(t, configuration.CheckModes(checkedProject.ProjectType)[checkmode.Official], projectConfigurationReport.Official)
83-
98+
assert.Equal(t, 1, len(results.Projects[0].Checks), "Passing check reports should be written to report in verbose mode")
8499
checkReport := projectReport.Checks[0]
85100
assert.Equal(t, checkConfiguration.Category, checkReport.Category)
86101
assert.Equal(t, checkConfiguration.Subcategory, checkReport.Subcategory)
@@ -92,15 +107,25 @@ func TestRecord(t *testing.T) {
92107
assert.Equal(t, checkLevel.String(), checkReport.Level)
93108
assert.Equal(t, checkOutput, checkReport.Message)
94109

110+
flags.Set("verbose", "false")
111+
require.Nil(t, configuration.Initialize(flags, projectPaths))
112+
results.Initialize()
113+
results.Record(checkedProject, checkConfiguration, checkresult.Pass, checkOutput)
114+
assert.Equal(t, 0, len(results.Projects[0].Checks), "Passing check reports should not be written to report in non-verbose mode")
115+
116+
results.Initialize()
117+
results.Record(checkedProject, checkConfiguration, checkresult.Fail, checkOutput)
118+
require.Equal(t, 1, len(projectReport.Checks), "Failing check reports should be written to report in non-verbose mode")
119+
95120
assert.Len(t, results.Projects, 1)
96121
previousProjectPath := checkedProject.Path
97122
checkedProject.Path = paths.New("/foo/baz")
98-
results.Record(checkedProject, checkConfiguration, checkResult, checkOutput)
123+
results.Record(checkedProject, checkConfiguration, checkresult.Fail, checkOutput)
99124
assert.Len(t, results.Projects, 2)
100125

101126
assert.Len(t, results.Projects[0].Checks, 1)
102127
checkedProject.Path = previousProjectPath
103-
results.Record(checkedProject, checkconfigurations.Configurations()[1], checkResult, checkOutput)
128+
results.Record(checkedProject, checkconfigurations.Configurations()[1], checkresult.Fail, checkOutput)
104129
assert.Len(t, results.Projects[0].Checks, 2)
105130
}
106131

@@ -114,40 +139,61 @@ func TestAddProjectSummary(t *testing.T) {
114139
testTables := []struct {
115140
results []checkresult.Type
116141
levels []checklevel.Type
142+
verbose string
117143
expectedPass bool
118144
expectedWarningCount int
119145
expectedErrorCount int
120146
}{
121147
{
122148
[]checkresult.Type{checkresult.Pass, checkresult.Pass},
123149
[]checklevel.Type{checklevel.Info, checklevel.Info},
150+
"true",
151+
true,
152+
0,
153+
0,
154+
},
155+
{
156+
[]checkresult.Type{checkresult.Pass, checkresult.Pass},
157+
[]checklevel.Type{checklevel.Info, checklevel.Info},
158+
"false",
124159
true,
125160
0,
126161
0,
127162
},
128163
{
129164
[]checkresult.Type{checkresult.Pass, checkresult.Fail},
130165
[]checklevel.Type{checklevel.Info, checklevel.Warning},
166+
"false",
131167
true,
132168
1,
133169
0,
134170
},
135171
{
136172
[]checkresult.Type{checkresult.Fail, checkresult.Fail},
137173
[]checklevel.Type{checklevel.Error, checklevel.Warning},
174+
"false",
138175
false,
139176
1,
140177
1,
141178
},
142179
}
143180

144181
for _, testTable := range testTables {
182+
flags := test.ConfigurationFlags()
183+
flags.Set("verbose", testTable.verbose)
184+
require.Nil(t, configuration.Initialize(flags, projectPaths))
185+
145186
var results Type
146-
for _, result := range testTable.results {
187+
results.Initialize()
188+
189+
checkIndex := 0
190+
for testDataIndex, result := range testTable.results {
147191
results.Record(checkedProject, checkconfigurations.Configurations()[0], result, "")
148-
}
149-
for checkIndex, level := range testTable.levels {
150-
results.Projects[0].Checks[checkIndex].Level = level.String()
192+
if (result == checkresult.Fail) || configuration.Verbose() {
193+
level := testTable.levels[testDataIndex].String()
194+
results.Projects[0].Checks[checkIndex].Level = level
195+
checkIndex += 1
196+
}
151197
}
152198
results.AddProjectSummary(checkedProject)
153199
assert.Equal(t, testTable.expectedPass, results.Projects[0].Summary.Pass)
@@ -243,10 +289,6 @@ func TestAddSummary(t *testing.T) {
243289
func TestWriteReport(t *testing.T) {
244290
flags := test.ConfigurationFlags()
245291

246-
projectPath, err := os.Getwd() // Path to an arbitrary folder that is guaranteed to exist.
247-
require.Nil(t, err)
248-
projectPaths := []string{projectPath}
249-
250292
reportFolderPathString, err := ioutil.TempDir("", "arduino-check-result-TestWriteReport")
251293
require.Nil(t, err)
252294
defer os.RemoveAll(reportFolderPathString) // clean up

Diff for: util/test/test.go

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ func ConfigurationFlags() *pflag.FlagSet {
2929
flags.String("project-type", "all", "")
3030
flags.Bool("recursive", true, "")
3131
flags.String("report-file", "", "")
32+
flags.Bool("verbose", false, "")
3233
flags.Bool("version", false, "")
3334

3435
return flags

0 commit comments

Comments
 (0)