Skip to content

Commit

Permalink
Merge pull request #30 from green-code-initiative/ISSUE_29
Browse files Browse the repository at this point in the history
Add test to ensure all Rules are registered
  • Loading branch information
dedece35 authored Jul 26, 2024
2 parents 6e9fc8d + dbf7fd7 commit 869c07f
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 90 deletions.
22 changes: 15 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- refactoring docker system
- [#29](https://github.com/green-code-initiative/ecoCode-python/issues/29) Add test to ensure all Rules are registered

### Deleted

Expand All @@ -23,7 +24,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- [#22](https://github.com/green-code-initiative/ecoCode-python/issues/22) Depreciation of EC69 rule for python because not relevant (after analysis)
- [#22](https://github.com/green-code-initiative/ecoCode-python/issues/22) Depreciation of EC69 rule for python because
not relevant (after analysis)

### Deleted

Expand All @@ -33,12 +35,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- [#18](https://github.com/green-code-initiative/ecoCode-python/issues/18) Add support for SonarQube 10.4 "DownloadOnlyWhenRequired" feature
- [#18](https://github.com/green-code-initiative/ecoCode-python/issues/18) Add support for SonarQube 10.4 "
DownloadOnlyWhenRequired" feature
- Add Support for SonarQube 10.4.1

### Changed

- [#17](https://github.com/green-code-initiative/ecoCode-python/issues/17) EC7 - correction setter problem on constructor method
- [#17](https://github.com/green-code-initiative/ecoCode-python/issues/17) EC7 - correction setter problem on
constructor method
- check Sonarqube 10.4.1 compatibility + update docker files and README.md / NOT OK with 10.5.x (issue created)

## [1.4.2] - 2024-01-11
Expand All @@ -56,8 +60,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- [#5](https://github.com/green-code-initiative/ecoCode-python/pull/5) Upgrade licence system and licence headers of Java files
- [#6](https://github.com/green-code-initiative/ecoCode-python/pull/6) Adding EC35 rule : EC35 rule replaces EC34 with a specific use case ("file not found" sepcific)
- [#5](https://github.com/green-code-initiative/ecoCode-python/pull/5) Upgrade licence system and licence headers of
Java files
- [#6](https://github.com/green-code-initiative/ecoCode-python/pull/6) Adding EC35 rule : EC35 rule replaces EC34 with a
specific use case ("file not found" sepcific)
- [#7](https://github.com/green-code-initiative/ecoCode-python/issues/7) Add build number to manifest
- [#123](https://github.com/green-code-initiative/ecoCode/issues/123) Improve unit tests for EC7 rule
- Update ecocode-rules-specifications to 1.4.6
Expand All @@ -66,14 +72,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Deleted

- [#4](https://github.com/green-code-initiative/ecoCode-python/issues/4) Deprecate rule EC66 for Python because not applicable (see details inside issue)
- [#4](https://github.com/green-code-initiative/ecoCode-python/issues/4) Deprecate rule EC66 for Python because not
applicable (see details inside issue)

## [1.4.0] - 2023-08-08

### Added

- Python rules moved from `ecoCode` repository to current repository
- [#142](https://github.com/green-code-initiative/ecoCode/issues/142) new Python rule : Multiple if-else statement + refactoring implementation
- [#142](https://github.com/green-code-initiative/ecoCode/issues/142) new Python rule : Multiple if-else statement +
refactoring implementation
- [#205](https://github.com/green-code-initiative/ecoCode/issues/205) compatibility with SonarQube 10.1

## Comparison list
Expand Down
10 changes: 9 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>io.ecocode</groupId>
Expand Down Expand Up @@ -110,6 +111,13 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.10.2</version>
<scope>test</scope>
</dependency>

</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,33 +28,7 @@

public class PythonRuleRepository implements RulesDefinition, PythonCustomRuleRepository {

public static final String LANGUAGE = "py";
public static final String NAME = "ecoCode";
public static final String RESOURCE_BASE_PATH = "io/ecocode/rules/python";
public static final String REPOSITORY_KEY = "ecocode-python";

private final SonarRuntime sonarRuntime;

public PythonRuleRepository(SonarRuntime sonarRuntime) {
this.sonarRuntime = sonarRuntime;
}

@Override
public void define(Context context) {
NewRepository repository = context.createRepository(REPOSITORY_KEY, LANGUAGE).setName(NAME);
RuleMetadataLoader ruleMetadataLoader = new RuleMetadataLoader(RESOURCE_BASE_PATH, sonarRuntime);
ruleMetadataLoader.addRulesByAnnotatedClass(repository, (List) checkClasses());
repository.done();
}

@Override
public String repositoryKey() {
return REPOSITORY_KEY;
}

@Override
public List<Class> checkClasses() {
return Arrays.asList(
static final List<Class> ANNOTATED_RULE_CLASSES = Arrays.asList(
AvoidGettersAndSetters.class,
AvoidGlobalVariableInFunctionCheck.class,
AvoidSQLRequestInLoop.class,
Expand All @@ -67,5 +41,33 @@ public List<Class> checkClasses() {
DetectUnoptimizedImageFormat.class,
AvoidMultipleIfElseStatementCheck.class
);
}

public static final String LANGUAGE = "py";
public static final String NAME = "ecoCode";
public static final String RESOURCE_BASE_PATH = "io/ecocode/rules/python";
public static final String REPOSITORY_KEY = "ecocode-python";

private final SonarRuntime sonarRuntime;

public PythonRuleRepository(SonarRuntime sonarRuntime) {
this.sonarRuntime = sonarRuntime;
}

@Override
public void define(Context context) {
NewRepository repository = context.createRepository(REPOSITORY_KEY, LANGUAGE).setName(NAME);
RuleMetadataLoader ruleMetadataLoader = new RuleMetadataLoader(RESOURCE_BASE_PATH, sonarRuntime);
ruleMetadataLoader.addRulesByAnnotatedClass(repository, (List) checkClasses());
repository.done();
}

@Override
public String repositoryKey() {
return REPOSITORY_KEY;
}

@Override
public List<Class> checkClasses() {
return ANNOTATED_RULE_CLASSES;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.reflections.Reflections;
import org.sonar.api.SonarRuntime;
import org.sonar.api.server.rule.RulesDefinition;
import org.sonar.api.utils.Version;
import org.sonar.check.Rule;

import java.util.Set;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
Expand All @@ -32,11 +36,12 @@

class PythonRuleRepositoryTest {

private RulesDefinition.Repository repository;
private PythonRuleRepository rulesDefinition;
private RulesDefinition.Repository repository;

@BeforeEach
void init() {
// TODO: Remove this check after Git repo split
@BeforeEach
void init() {
// TODO: Remove this check after Git repo split
/*
On an IDE (like IntelliJ), if the developer runs the unit tests without building/generating the Maven goals on the
"ecocode-rules-specifications" module before, the unit tests will not see the generated HTML descriptions (from ASCIIDOC files).
Expand All @@ -45,60 +50,72 @@ On an IDE (like IntelliJ), if the developer runs the unit tests without building
When the `python-plugin` submodule is in a specific Git repository, `ecocode-rules-specifications` will be fetched from a classic
external Maven dependency. There will therefore no longer be any need to perform this specific configuration.
*/
if (PythonRuleRepository.class.getResource("/io/ecocode/rules/python/EC4.json") == null) {
String message = "'ecocode-rules-specification' resources corrupted. Please check build of 'ecocode-rules-specification' module";
if (System.getProperties().keySet().stream().anyMatch(k -> k.toString().startsWith("idea."))) {
message += "\n\nOn 'IntelliJ IDEA':" +
"\n1. go to settings :" +
"\n > Build, Execution, Deployment > Build Tools > Maven > Runner" +
"\n2. check option:" +
"\n > Delegate IDE build/run actions to Maven" +
"\n3. Click on menu: " +
"\n > Build > Build Project"
;
}
fail(message);
if (PythonRuleRepository.class.getResource("/io/ecocode/rules/python/EC4.json") == null) {
String message = "'ecocode-rules-specification' resources corrupted. Please check build of 'ecocode-rules-specification' module";
if (System.getProperties().keySet().stream().anyMatch(k -> k.toString().startsWith("idea."))) {
message += "\n\nOn 'IntelliJ IDEA':" +
"\n1. go to settings :" +
"\n > Build, Execution, Deployment > Build Tools > Maven > Runner" +
"\n2. check option:" +
"\n > Delegate IDE build/run actions to Maven" +
"\n3. Click on menu: " +
"\n > Build > Build Project"
;
}
fail(message);
}

final SonarRuntime sonarRuntime = mock(SonarRuntime.class);
doReturn(Version.create(0, 0)).when(sonarRuntime).getApiVersion();
rulesDefinition = new PythonRuleRepository(sonarRuntime);
RulesDefinition.Context context = new RulesDefinition.Context();
rulesDefinition.define(context);
repository = context.repository(rulesDefinition.repositoryKey());
}

final SonarRuntime sonarRuntime = mock(SonarRuntime.class);
doReturn(Version.create(0, 0)).when(sonarRuntime).getApiVersion();
PythonRuleRepository rulesDefinition = new PythonRuleRepository(sonarRuntime);
RulesDefinition.Context context = new RulesDefinition.Context();
rulesDefinition.define(context);
repository = context.repository(rulesDefinition.repositoryKey());
}
@Test
@DisplayName("Test repository metadata")
void testMetadata() {
assertThat(repository.name()).isEqualTo("ecoCode");
assertThat(repository.language()).isEqualTo("py");
assertThat(repository.key()).isEqualTo("ecocode-python");
}

@Test
@DisplayName("Test repository metadata")
void testMetadata() {
assertThat(repository.name()).isEqualTo("ecoCode");
assertThat(repository.language()).isEqualTo("py");
assertThat(repository.key()).isEqualTo("ecocode-python");
}
@Test
void testRegistredRules() {
assertThat(rulesDefinition.checkClasses())
.describedAs("All implemented rules must be registered into " + PythonRuleRepository.class)
.containsExactlyInAnyOrder(getDefinedRules().toArray(new Class[0]));
}

@Test
void testRegistredRules() {
assertThat(repository.rules()).hasSize(11);
}
@Test
void checkNumberRules() {
assertThat(repository.rules()).hasSize(PythonRuleRepository.ANNOTATED_RULE_CLASSES.size());
}

@Test
@DisplayName("All rule keys must be prefixed by 'EC'")
void testRuleKeyPrefix() {
SoftAssertions assertions = new SoftAssertions();
repository.rules().forEach(
rule -> assertions.assertThat(rule.key()).startsWith("EC")
);
assertions.assertAll();
}
@Test
@DisplayName("All rule keys must be prefixed by 'EC'")
void testRuleKeyPrefix() {
SoftAssertions assertions = new SoftAssertions();
repository.rules().forEach(
rule -> assertions.assertThat(rule.key()).startsWith("EC")
);
assertions.assertAll();
}

@Test
void testAllRuleParametersHaveDescription() {
SoftAssertions assertions = new SoftAssertions();
repository.rules().stream()
.flatMap(rule -> rule.params().stream())
.forEach(param -> assertions.assertThat(param.description())
.as("description for " + param.key())
.isNotEmpty());
assertions.assertAll();
}

@Test
void testAllRuleParametersHaveDescription() {
SoftAssertions assertions = new SoftAssertions();
repository.rules().stream()
.flatMap(rule -> rule.params().stream())
.forEach(param -> assertions.assertThat(param.description())
.as("description for " + param.key())
.isNotEmpty());
assertions.assertAll();
}
private static Set<Class<?>> getDefinedRules() {
Reflections r = new Reflections(PythonRuleRepository.class.getPackageName() + ".checks");
return r.getTypesAnnotatedWith(Rule.class);
}
}

0 comments on commit 869c07f

Please sign in to comment.