Skip to content

Commit aec09b9

Browse files
Adds ArchUnit tests for naming conventions (#2077)
* Add archunit tests for naming conventions Signed-off-by: solonovamax <solonovamax@12oclockpoint.com> * Fix javadoc warnings Signed-off-by: solonovamax <solonovamax@12oclockpoint.com> * Update src/test/java/org/kohsuke/github/ArchTests.java * Update src/test/java/org/kohsuke/github/ArchTests.java * Update src/test/java/org/kohsuke/github/ArchTests.java * Update src/test/java/org/kohsuke/github/ArchTests.java * Update src/test/java/org/kohsuke/github/ArchTests.java * Fix inherited methods --------- Signed-off-by: solonovamax <solonovamax@12oclockpoint.com> Co-authored-by: Liam Newman <bitwiseman@gmail.com>
1 parent 1225510 commit aec09b9

File tree

1 file changed

+105
-3
lines changed

1 file changed

+105
-3
lines changed

src/test/java/org/kohsuke/github/ArchTests.java

Lines changed: 105 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
package org.kohsuke.github;
22

33
import com.tngtech.archunit.base.DescribedPredicate;
4+
import com.tngtech.archunit.base.HasDescription;
45
import com.tngtech.archunit.core.domain.*;
56
import com.tngtech.archunit.core.domain.properties.HasName;
67
import com.tngtech.archunit.core.domain.properties.HasOwner;
8+
import com.tngtech.archunit.core.domain.properties.HasSourceCodeLocation;
79
import com.tngtech.archunit.core.importer.ClassFileImporter;
810
import com.tngtech.archunit.core.importer.ImportOption;
911
import com.tngtech.archunit.lang.ArchCondition;
1012
import com.tngtech.archunit.lang.ArchRule;
13+
import com.tngtech.archunit.lang.conditions.ArchConditions;
1114
import org.apache.commons.io.IOUtils;
1215
import org.apache.commons.lang3.StringUtils;
1316
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
1417
import org.apache.commons.lang3.builder.ToStringBuilder;
1518
import org.apache.commons.lang3.builder.ToStringStyle;
1619
import org.junit.BeforeClass;
1720
import org.junit.Test;
21+
import org.kohsuke.github.GHDiscussion.Creator;
22+
import org.kohsuke.github.GHPullRequestCommitDetail.Commit;
23+
import org.kohsuke.github.GHPullRequestCommitDetail.CommitPointer;
1824

1925
import java.io.Closeable;
2026
import java.io.InputStream;
@@ -26,22 +32,34 @@
2632
import java.util.stream.Collectors;
2733

2834
import static com.google.common.base.Preconditions.checkNotNull;
35+
import static com.tngtech.archunit.base.DescribedPredicate.not;
36+
import static com.tngtech.archunit.base.DescribedPredicate.or;
2937
import static com.tngtech.archunit.core.domain.JavaCall.Predicates.target;
38+
import static com.tngtech.archunit.core.domain.JavaClass.Predicates.assignableTo;
3039
import static com.tngtech.archunit.core.domain.JavaClass.Predicates.resideInAPackage;
3140
import static com.tngtech.archunit.core.domain.JavaClass.Predicates.type;
41+
import static com.tngtech.archunit.core.domain.JavaMember.Predicates.declaredIn;
42+
import static com.tngtech.archunit.core.domain.JavaModifier.FINAL;
43+
import static com.tngtech.archunit.core.domain.JavaModifier.STATIC;
44+
import static com.tngtech.archunit.core.domain.properties.HasModifiers.Predicates.modifier;
3245
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.name;
3346
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameContaining;
3447
import static com.tngtech.archunit.core.domain.properties.HasOwner.Predicates.With.owner;
3548
import static com.tngtech.archunit.core.domain.properties.HasParameterTypes.Predicates.rawParameterTypes;
3649
import static com.tngtech.archunit.lang.conditions.ArchConditions.*;
3750
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
51+
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
52+
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noFields;
53+
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noMethods;
3854
import static org.hamcrest.MatcherAssert.assertThat;
3955
import static org.hamcrest.Matchers.greaterThan;
4056

4157
// TODO: Auto-generated Javadoc
4258
/**
4359
* The Class ArchTests.
4460
*/
61+
@SuppressWarnings({ "LocalVariableNamingConvention", "TestMethodWithoutAssertion", "UnqualifiedStaticUsage",
62+
"unchecked", "MethodMayBeStatic", "FieldNamingConvention", "StaticCollection" })
4563
public class ArchTests {
4664

4765
private static final JavaClasses classFiles = new ClassFileImporter()
@@ -69,6 +87,46 @@ public static void beforeClass() {
6987
assertThat(classFiles.size(), greaterThan(0));
7088
}
7189

90+
/**
91+
* Test naming conventions
92+
*/
93+
@Test
94+
public void testRequireFollowingNamingConvention() {
95+
final String reason = "This project follows standard java naming conventions and does not allow the use of underscores in names.";
96+
97+
final ArchRule fieldsNotFollowingConvention = noFields().that()
98+
.arePublic()
99+
.and(not(enumConstants()))
100+
.and(not(modifier(STATIC).and(modifier(FINAL)).as("static final")))
101+
.should(haveNamesContainingUnless("_"))
102+
.because(reason);
103+
104+
@SuppressWarnings("AccessStaticViaInstance")
105+
final ArchRule methodsNotFollowingConvention = noMethods().that()
106+
.arePublic()
107+
.should(haveNamesContainingUnless("_",
108+
// currently failing method names
109+
// TODO: 2025-03-28 Fix & remove these
110+
declaredIn(assignableTo(PagedIterable.class)).and(name("_iterator")),
111+
declaredIn(GHCompare.class).and(name("getAdded_by")),
112+
declaredIn(GHDeployKey.class).and(name("getAdded_by")),
113+
declaredIn(GHDeployKey.class).and(name("isRead_only")),
114+
declaredIn(assignableTo(GHRepositoryBuilder.class)).and(name("private_")),
115+
declaredIn(Creator.class).and(name("private_")),
116+
declaredIn(GHGistBuilder.class).and(name("public_")),
117+
declaredIn(Commit.class).and(name("getComment_count")),
118+
declaredIn(CommitPointer.class).and(name("getHtml_url")),
119+
declaredIn(GHRelease.class).and(name("getPublished_at"))))
120+
.because(reason);
121+
122+
final ArchRule classesNotFollowingConvention = noClasses().should(haveNamesContainingUnless("_"))
123+
.because(reason);
124+
125+
fieldsNotFollowingConvention.check(classFiles);
126+
methodsNotFollowingConvention.check(classFiles);
127+
classesNotFollowingConvention.check(classFiles);
128+
}
129+
72130
/**
73131
* Test require use of assert that.
74132
*/
@@ -78,10 +136,10 @@ public void testRequireUseOfAssertThat() {
78136
final String reason = "This project uses `assertThat(...)` or `assertThrows(...)` instead of other `assert*()` methods.";
79137

80138
final DescribedPredicate<HasName> assertMethodOtherThanAssertThat = nameContaining("assert")
81-
.and(DescribedPredicate.not(name("assertThat")).and(DescribedPredicate.not(name("assertThrows"))));
139+
.and(not(name("assertThat")).and(not(name("assertThrows"))));
82140

83141
final ArchRule onlyAssertThatRule = classes()
84-
.should(not(callMethodWhere(target(assertMethodOtherThanAssertThat))))
142+
.should(ArchConditions.not(callMethodWhere(target(assertMethodOtherThanAssertThat))))
85143
.because(reason);
86144

87145
onlyAssertThatRule.check(testClassFiles);
@@ -135,6 +193,29 @@ public void testRequireUseOfOnlySpecificApacheCommons() {
135193
onlyApprovedApacheCommonsMethods.check(classFiles);
136194
}
137195

196+
/**
197+
* Have names containing unless.
198+
*
199+
* @param <T>
200+
* the generic type
201+
* @param infix
202+
* the infix
203+
* @param unlessPredicates
204+
* the unless predicates
205+
* @return the arch condition
206+
*/
207+
public static <T extends HasDescription & HasSourceCodeLocation & HasName> ArchCondition<T> haveNamesContainingUnless(
208+
final String infix,
209+
final DescribedPredicate<? super T>... unlessPredicates) {
210+
DescribedPredicate<? super T> restrictedNameContaining = nameContaining(infix);
211+
212+
if (unlessPredicates.length > 0) {
213+
final DescribedPredicate<T> allowed = or(unlessPredicates);
214+
restrictedNameContaining = unless(nameContaining(infix), allowed);
215+
}
216+
return have(restrictedNameContaining);
217+
}
218+
138219
/**
139220
* Not call methods in package unless.
140221
*
@@ -156,7 +237,7 @@ public static ArchCondition<JavaClass> notCallMethodsInPackageUnless(final Strin
156237
}
157238
restrictedPackageCalls = unless(restrictedPackageCalls, allowed);
158239
}
159-
return not(callMethodWhere(restrictedPackageCalls));
240+
return ArchConditions.not(callMethodWhere(restrictedPackageCalls));
160241
}
161242

162243
/**
@@ -200,6 +281,15 @@ public static <T> DescribedPredicate<T> unless(DescribedPredicate<? super T> fir
200281
return new UnlessPredicate(first, second);
201282
}
202283

284+
/**
285+
* Enum constants.
286+
*
287+
* @return the described predicate
288+
*/
289+
private DescribedPredicate<? super JavaField> enumConstants() {
290+
return new EnumConstantFieldPredicate();
291+
}
292+
203293
private static class UnlessPredicate<T> extends DescribedPredicate<T> {
204294
private final DescribedPredicate<T> current;
205295
private final DescribedPredicate<? super T> other;
@@ -215,4 +305,16 @@ public boolean test(T input) {
215305
return current.test(input) && !other.test(input);
216306
}
217307
}
308+
309+
private static final class EnumConstantFieldPredicate extends DescribedPredicate<JavaField> {
310+
private EnumConstantFieldPredicate() {
311+
super("are not enum constants");
312+
}
313+
314+
@Override
315+
public boolean test(JavaField javaField) {
316+
JavaClass owner = javaField.getOwner();
317+
return owner.isEnum() && javaField.getRawType().isAssignableTo(owner.reflect());
318+
}
319+
}
218320
}

0 commit comments

Comments
 (0)