Annahmen: Java11, JUnit5, sbt
Ich habe die Monstermethode satt, also habe ich so etwas geschrieben ... Bereiten wir es zu Beginn des Projekts vor.
Als Ergebnis der Vorbereitung so etwas Ich habe die Methoden aufgeteilt und vorerst die Anzahl der Zeilen pro Methode reduziert, Stattdessen könnte es zu einer globalen Variablen gemacht werden, indem der Bereich der Variablen erweitert wird, sodass mit verschiedenen Methoden auf sie verwiesen werden kann. Es gibt ein Problem, dass ... Vielleicht ist es dieses Mal noch besser, dieses vorzubereiten? Ich denke.
Fügen Sie ↓ in libraryDependencies von build.sbt ein
build.sbt
"org.junit.jupiter" % "junit-jupiter-api" % "5.5.0",
"org.junit.jupiter"%"junit-jupiter-engine" % "5.5.0",
"org.javassist" % "javassist" % "3.25.0-GA",
package com.github.momosetkn;
import javassist.ClassPool;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
class MonsterMethodAlert {
@Test
void test() throws Exception {
var cp = ClassPool.getDefault();
var fail = false;
for (var className : getClassNameList()) {
var cc = cp.get(className);
for (var method : cc.getMethods()) {
// java.lang.Object.Methoden unter Java-Paket wie gleich sind ausgeschlossen
if (method.getDeclaringClass().getName().startsWith("java"))
continue;
var methodInfo = method.getMethodInfo();
var start = methodInfo.getLineNumber(Integer.MIN_VALUE);
var end = methodInfo.getLineNumber(Integer.MAX_VALUE);
var line = end - start + 1;
if (line >= 25) {
System.err.println(String.format("%s%Es ist eine Monstermethode der Linie", className + "#" + methodInfo.getName(), line));
fail = true;
}
}
}
if (fail)
throw new Exception("Monstermethode erkannt");
}
private List<String> getClassNameList() throws IOException, URISyntaxException {
var list = new ArrayList<String>();
var classLoader = Thread.currentThread().getContextClassLoader();
var targetUrls = classLoader.getResources("");
var CLASS_EXT = ".class";
while (targetUrls.hasMoreElements()) {
var url = targetUrls.nextElement();
if (!url.getProtocol().equals("file")) {
continue;
}
var targetPath = Paths.get(url.toURI());
Files.walkFileTree(targetPath, new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path foundPath, BasicFileAttributes attrs) throws IOException {
if (foundPath.toString().endsWith(CLASS_EXT)){
var relativizeStr = targetPath.relativize(foundPath).toString();
list.add(
relativizeStr
.substring(0, relativizeStr.length() - CLASS_EXT.length())
.replace(File.separatorChar, '.')
);
}
return super.visitFile(foundPath, attrs);
}
});
}
return list;
}
}
Example#main ist eine 36-zeilige Monstermethode
java.lang.Exception:Monstermethode erkannt
at com.github.momosetkn.MonsterMethodAlert.test(MonsterMethodAlert.java:37)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:436)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:170)
at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:166)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:113)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:58)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:112)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:55)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Betrachtet man die Implementierung von javassist.bytecode.MethodInfo # getLineNumber
,
Es scheint, dass der an das Argument übergebene numerische Wert an die folgende Methode übergeben wird.
https://github.com/jboss-javassist/javassist/blob/rel_3_25_0_ga/src/main/javassist/bytecode/LineNumberAttribute.java#L77
Es scheint, dass es nur beurteilt wird, indem man es in einer Schleife dreht und überschreitet, also
Wir übergeben "Integer.MIN_VALUE" und "Integer.MAX_VALUE".
Anfang und Ende sind
100: public void method(){
101: //Start ist hier die Anzahl der Zeilen
102: //
103: //Ende ist die Anzahl der Zeilen hier
104: }
Da 103-102 = 2 ist, wird es als Methode mit 1 hinzugefügten und 3 Zeilen behandelt.
Ältere Versionen von Javassist folgen nicht der neueren Java-Version, machen Sie sie also so neu wie möglich.
Ich möchte die Liste der Klassen unter dem Paket \ -Qiita rekursiv durchsuchen Javassist-Memo \ (Hishidamas Javassist-Memo )
Recommended Posts