Skip to content
This repository was archived by the owner on Jul 8, 2019. It is now read-only.

Commit f45aff4

Browse files
committed
Improving test coverage, fixing minor NCLOC miscounting issue
1 parent 37a0344 commit f45aff4

File tree

12 files changed

+237
-31
lines changed

12 files changed

+237
-31
lines changed

src/main/java/com/pablissimo/sonar/LOCSensor.java

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,52 +8,50 @@
88
import org.sonar.api.batch.SensorContext;
99
import org.sonar.api.batch.fs.FileSystem;
1010
import org.sonar.api.batch.fs.InputFile;
11-
import org.sonar.api.config.Settings;
1211
import org.sonar.api.measures.CoreMetrics;
13-
import org.sonar.api.measures.FileLinesContextFactory;
1412
import org.sonar.api.measures.Measure;
1513
import org.sonar.api.resources.Project;
1614

1715
public class LOCSensor implements Sensor {
18-
19-
private Settings settings;
20-
private FileSystem fs;
16+
private FileSystem fileSystem;
2117

2218
/**
2319
* Use of IoC to get Settings and FileSystem
2420
*/
25-
public LOCSensor(FileLinesContextFactory _fileLinesContextFactory,
26-
Settings settings, FileSystem fs) {
27-
this.settings = settings;
28-
this.fs = fs;
21+
public LOCSensor(FileSystem fs) {
22+
this.fileSystem = fs;
2923
}
3024

3125
public boolean shouldExecuteOnProject(Project project) {
3226
// This sensor is executed only when there are TypeScript files
33-
return fs.hasFiles(fs.predicates().hasLanguage("ts"));
27+
return fileSystem.hasFiles(fileSystem.predicates().hasLanguage("ts"));
3428
}
3529

3630
public void analyse(Project project, SensorContext sensorContext) {
3731
// This sensor count the Line of source code in every .ts file
3832

39-
for (InputFile inputFile : fs.inputFiles(fs.predicates().hasLanguage(
33+
for (InputFile inputFile : fileSystem.inputFiles(fileSystem.predicates().hasLanguage(
4034
"ts"))) {
41-
double value = this.getNumberCodeLine(inputFile);
35+
int value = this.getNonCommentLineCount(inputFile);
4236
sensorContext.saveMeasure(inputFile, new Measure<Integer>(
43-
CoreMetrics.NCLOC, value));
37+
CoreMetrics.NCLOC, (double) value));
4438
}
4539
}
4640

4741
@Override
4842
public String toString() {
4943
return getClass().getSimpleName();
5044
}
45+
46+
protected BufferedReader getReaderFromFile(InputFile inputFile) throws FileNotFoundException {
47+
return new BufferedReader(new FileReader(inputFile.file()));
48+
}
5149

52-
private double getNumberCodeLine(InputFile inputFile) {
53-
double value = 0;
50+
private int getNonCommentLineCount(InputFile inputFile) {
51+
int value = 0;
5452
BufferedReader br;
5553
try {
56-
br = new BufferedReader(new FileReader(inputFile.file()));
54+
br = this.getReaderFromFile(inputFile);
5755

5856
boolean isEOF = false;
5957
boolean isCommentOpen = false;
@@ -62,7 +60,7 @@ private double getNumberCodeLine(InputFile inputFile) {
6260

6361
String line = br.readLine();
6462
if (line != null) {
65-
isACommentLine = false;
63+
isACommentLine = isCommentOpen;
6664
line = line.trim();
6765

6866
if (isCommentOpen) {

src/main/java/com/pablissimo/sonar/TsLintExecutorImpl.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,12 @@ public void consumeLine(String line) {
4040
}
4141
};
4242

43-
CommandExecutor executor = CommandExecutor.create();
44-
int exitCode = executor.execute(command, stdOutConsumer, stdErrConsumer, 5000);
43+
this.createExecutor().execute(command, stdOutConsumer, stdErrConsumer, 5000);
4544

4645
return stdOut.toString();
4746
}
47+
48+
protected CommandExecutor createExecutor() {
49+
return CommandExecutor.create();
50+
}
4851
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
package com.pablissimo.sonar;
2+
3+
import static org.junit.Assert.*;
4+
import static org.mockito.Matchers.any;
5+
import static org.mockito.Mockito.*;
6+
7+
import java.io.BufferedReader;
8+
import java.io.File;
9+
import java.io.FileNotFoundException;
10+
import java.io.InputStream;
11+
import java.io.InputStreamReader;
12+
import java.net.URL;
13+
import java.util.ArrayList;
14+
import java.util.Arrays;
15+
import java.util.List;
16+
17+
import org.junit.Before;
18+
import org.junit.Test;
19+
import org.mockito.invocation.InvocationOnMock;
20+
import org.mockito.stubbing.Answer;
21+
import org.sonar.api.batch.SensorContext;
22+
import org.sonar.api.batch.fs.FilePredicate;
23+
import org.sonar.api.batch.fs.FilePredicates;
24+
import org.sonar.api.batch.fs.FileSystem;
25+
import org.sonar.api.batch.fs.InputFile;
26+
import org.sonar.api.measures.CoreMetrics;
27+
import org.sonar.api.measures.Measure;
28+
29+
public class LOCSensorTest {
30+
FileSystem fileSystem;
31+
FilePredicates filePredicates;
32+
FilePredicate predicate;
33+
34+
List<File> files;
35+
File file;
36+
37+
LOCSensor sensor;
38+
39+
SensorContext sensorContext;
40+
41+
@Before
42+
public void setUp() throws Exception {
43+
this.file = mock(File.class);
44+
doReturn(true).when(this.file).isFile();
45+
46+
this.files = new ArrayList<File>(Arrays.asList(new File[] {
47+
this.file
48+
}));
49+
50+
ArrayList<InputFile> inputFiles = new ArrayList<InputFile>();
51+
inputFiles.add(mock(InputFile.class));
52+
53+
this.fileSystem = mock(FileSystem.class);
54+
this.predicate = mock(FilePredicate.class);
55+
when(fileSystem.files(this.predicate)).thenReturn(this.files);
56+
when(fileSystem.inputFiles(this.predicate)).thenReturn(inputFiles);
57+
58+
this.sensorContext = mock(SensorContext.class);
59+
60+
this.filePredicates = mock(FilePredicates.class);
61+
when(this.fileSystem.predicates()).thenReturn(this.filePredicates);
62+
when(filePredicates.hasLanguage(TypeScriptLanguage.LANGUAGE_EXTENSION)).thenReturn(this.predicate);
63+
when(fileSystem.hasFiles(this.predicate)).thenReturn(true);
64+
65+
this.sensor = spy(new LOCSensor(this.fileSystem));
66+
}
67+
68+
@Test
69+
public void shouldExecuteOnProject_ReturnsTrue_WhenAnyTsFiles() {
70+
assertTrue(this.sensor.shouldExecuteOnProject(null));
71+
}
72+
73+
@Test
74+
public void shouldExecuteOnProject_ReturnsFalse_WhenNoTsFiles() {
75+
when(fileSystem.hasFiles(this.predicate)).thenReturn(false);
76+
assertFalse(this.sensor.shouldExecuteOnProject(null));
77+
}
78+
79+
@Test
80+
public void getStringReturnsClassName() {
81+
assertEquals("LOCSensor", new LOCSensor(this.fileSystem).toString());
82+
}
83+
84+
@Test
85+
public void basicBlockCommentsDiscounted() throws FileNotFoundException {
86+
assertLineCount("blockcomments1", 2);
87+
}
88+
89+
@Test
90+
public void blockCommentsNotConfusedWithNestedComments() throws FileNotFoundException {
91+
assertLineCount("blockcomments2", 2);
92+
}
93+
94+
@Test
95+
public void linesEndingWithABlockCommentStillCounted() throws FileNotFoundException {
96+
assertLineCount("blockcomments3", 1);
97+
}
98+
99+
@Test
100+
public void oneLineBlockCommentsDoNotConfuseCounting() throws FileNotFoundException {
101+
assertLineCount("blockcomments4", 1);
102+
}
103+
104+
@Test
105+
public void oneLineBlockCommentAtEndOfRealLineShouldNotConsiderNextLinesAsComments() throws FileNotFoundException {
106+
assertLineCount("blockcomments5", 2);
107+
}
108+
109+
@Test
110+
public void lineLevelCommentsAndWhitespaceHandledCorrectly() throws FileNotFoundException {
111+
assertLineCount("linecomments", 2);
112+
}
113+
114+
private void assertLineCount(String testName, int expected) throws FileNotFoundException {
115+
ClassLoader loader = getClass().getClassLoader();
116+
URL resource = loader.getResource("loc/" + testName + ".txt");
117+
InputStream stream = loader.getResourceAsStream("loc/" + testName + ".txt");
118+
this.file = new File(resource.getFile());
119+
120+
doReturn(new BufferedReader(new InputStreamReader(stream))).when(this.sensor).getReaderFromFile(any(InputFile.class));
121+
122+
final List<Measure<Integer>> capturedMeasures = new ArrayList<Measure<Integer>>();
123+
Answer<Void> captureMeasure = new Answer<Void>() {
124+
@Override
125+
public Void answer(InvocationOnMock invocation) throws Throwable {
126+
capturedMeasures.add((Measure<Integer>) invocation.getArguments()[1]);
127+
return null;
128+
}
129+
};
130+
131+
when(this.sensorContext.saveMeasure(any(InputFile.class), any(Measure.class))).then(captureMeasure);
132+
133+
this.sensor.analyse(null, this.sensorContext);
134+
135+
assertEquals(1, capturedMeasures.size());
136+
assertEquals(CoreMetrics.NCLOC, capturedMeasures.get(0).getMetric());
137+
assertEquals(expected, (int) capturedMeasures.get(0).getIntValue());
138+
}
139+
}

src/test/java/com/pablissimo/sonar/TsCoverageSensorTest.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,14 @@
99
import java.util.List;
1010
import java.util.Map;
1111

12-
import org.jfree.ui.action.DowngradeActionMap;
13-
import org.junit.After;
1412
import org.junit.Before;
1513
import org.junit.Test;
16-
import org.mockito.ArgumentCaptor;
1714
import org.mockito.invocation.InvocationOnMock;
1815
import org.mockito.stubbing.Answer;
1916
import org.sonar.api.batch.SensorContext;
2017
import org.sonar.api.batch.fs.FilePredicate;
2118
import org.sonar.api.batch.fs.FilePredicates;
2219
import org.sonar.api.batch.fs.FileSystem;
23-
import org.sonar.api.batch.fs.InputFile;
2420
import org.sonar.api.config.Settings;
2521
import org.sonar.api.measures.CoreMetrics;
2622
import org.sonar.api.measures.CoverageMeasuresBuilder;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.pablissimo.sonar;
2+
3+
import static org.junit.Assert.*;
4+
import static org.mockito.Mockito.*;
5+
6+
import java.util.ArrayList;
7+
import org.junit.Before;
8+
import org.junit.Test;
9+
import org.mockito.invocation.InvocationOnMock;
10+
import org.mockito.stubbing.Answer;
11+
import org.sonar.api.utils.command.Command;
12+
import org.sonar.api.utils.command.CommandExecutor;
13+
import org.sonar.api.utils.command.StreamConsumer;
14+
15+
public class TsLintExecutorImplTest {
16+
TsLintExecutorImpl executorImpl;
17+
CommandExecutor commandExecutor;
18+
19+
@Before
20+
public void setUp() throws Exception {
21+
this.commandExecutor = mock(CommandExecutor.class);
22+
this.executorImpl = spy(new TsLintExecutorImpl());
23+
when(this.executorImpl.createExecutor()).thenReturn(this.commandExecutor);
24+
}
25+
26+
@Test
27+
public void executesCommandWithCorrectArguments() {
28+
final ArrayList<Command> capturedCommands = new ArrayList<Command>();
29+
30+
Answer<Integer> captureCommand = new Answer<Integer>() {
31+
@Override
32+
public Integer answer(InvocationOnMock invocation) throws Throwable {
33+
capturedCommands.add((Command) invocation.getArguments()[0]);
34+
return 0;
35+
}
36+
};
37+
38+
when(this.commandExecutor.execute(any(Command.class), any(StreamConsumer.class), any(StreamConsumer.class), any(long.class))).then(captureCommand);
39+
this.executorImpl.execute("path/to/tslint", "path/to/config", "path/to/file");
40+
41+
assertEquals(1, capturedCommands.size());
42+
43+
Command theCommand = capturedCommands.get(0);
44+
45+
assertEquals("node path/to/tslint --format json --config path/to/config path/to/file", theCommand.toCommandLine());
46+
}
47+
}

src/test/java/com/pablissimo/sonar/TsLintSensorTest.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,13 @@
55

66
import java.io.File;
77
import java.io.IOException;
8-
import java.nio.charset.Charset;
98
import java.util.ArrayList;
9+
import java.util.Arrays;
1010
import java.util.List;
1111

12-
import org.apache.commons.io.Charsets;
1312
import org.junit.After;
1413
import org.junit.Before;
1514
import org.junit.Test;
16-
import org.mockito.ArgumentCaptor;
1715
import org.mockito.invocation.InvocationOnMock;
1816
import org.mockito.stubbing.Answer;
1917
import org.sonar.api.batch.SensorContext;
@@ -25,16 +23,11 @@
2523
import org.sonar.api.issue.Issuable;
2624
import org.sonar.api.issue.Issuable.IssueBuilder;
2725
import org.sonar.api.issue.Issue;
28-
import org.sonar.api.profiles.RulesProfile;
2926
import org.sonar.api.resources.Project;
3027
import org.sonar.api.rules.RuleFinder;
31-
import org.sonar.api.rules.RuleQuery;
32-
3328
import com.pablissimo.sonar.model.TsLintIssue;
3429
import com.pablissimo.sonar.model.TsLintPosition;
3530

36-
import edu.emory.mathcs.backport.java.util.Arrays;
37-
3831
public class TsLintSensorTest {
3932
Settings settings;
4033
FileSystem fileSystem;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/*
2+
Block comments shouldn't count towards line count - expected 2 lines
3+
*/
4+
module Whatever {
5+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/*
2+
Block comments tracking shouldn't get confused by
3+
other comment lines embedded in the block
4+
// like this
5+
nor by unexpected extra comment block openings
6+
/* like this
7+
*/
8+
module Whatever {
9+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
var x = 1; /*
2+
this block comment started somewhere unusual but shouldn't
3+
confuse things any - expecting one line
4+
*/
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/* We don't expect a one-line block comment to confuse things either */
2+
var x = 1;

0 commit comments

Comments
 (0)