This is an automated email from the ASF dual-hosted git repository. apolovtsev pushed a commit to branch ignite-20086 in repository https://gitbox.apache.org/repos/asf/ignite-3.git
commit 0beda7a18a8c8db934a4476a7b5fe5cf11edc601 Author: amashenkov <[email protected]> AuthorDate: Fri Jul 28 19:45:17 2023 +0300 Implement ArchUnit rule to detect wrong test classes hierarchy. --- .../internal/TestClassHierarchyArchTest.java | 65 ++++++++++++++++++++++ .../ignite/lang/TestsWithFixturesImportOption.java | 38 +++++++++++++ 2 files changed, 103 insertions(+) diff --git a/modules/arch-test/src/test/java/org/apache/ignite/internal/TestClassHierarchyArchTest.java b/modules/arch-test/src/test/java/org/apache/ignite/internal/TestClassHierarchyArchTest.java new file mode 100644 index 0000000000..915cb1b01f --- /dev/null +++ b/modules/arch-test/src/test/java/org/apache/ignite/internal/TestClassHierarchyArchTest.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal; + +import static com.tngtech.archunit.core.domain.properties.CanBeAnnotated.Predicates.annotatedWith; + +import com.tngtech.archunit.base.DescribedPredicate; +import com.tngtech.archunit.core.domain.AccessTarget; +import com.tngtech.archunit.core.domain.JavaCall; +import com.tngtech.archunit.core.domain.JavaClass.Functions; +import com.tngtech.archunit.core.domain.JavaClass.Predicates; +import com.tngtech.archunit.core.domain.properties.HasName; +import com.tngtech.archunit.junit.AnalyzeClasses; +import com.tngtech.archunit.junit.ArchTest; +import com.tngtech.archunit.lang.ArchRule; +import com.tngtech.archunit.lang.syntax.ArchRuleDefinition; +import org.apache.ignite.lang.LocationProvider.RootLocationProvider; +import org.apache.ignite.lang.TestsWithFixturesImportOption; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; + +/** + * Tests that tests classes, which uses Mockito spies, extends BaseIgniteAbstractTest. Using BaseIgniteAbstractTest guarantees the Mockito + * resources will be released after tests finishes. + */ +@SuppressWarnings("JUnitTestCaseWithNoTests") +@AnalyzeClasses( + packages = "org.apache.ignite", + importOptions = TestsWithFixturesImportOption.class, + locations = RootLocationProvider.class) +public class TestClassHierarchyArchTest { + private static final String BASE_IGNITE_ABSTRACT_TEST_CLASSNAME = "org.apache.ignite.internal.testframework.BaseIgniteAbstractTest"; + + @ArchTest + public static final ArchRule TEST_CLASS_WITH_MOCKS_EXTENDS_BASE_TEST_CLASS = ArchRuleDefinition + .classes() + // are classes with tests + .that(Predicates.containAnyMethodsThat(annotatedWith(Test.class).or(annotatedWith(ParameterizedTest.class)))) + // uses Mockito framework + .and(Functions.GET_METHOD_CALLS_FROM_SELF.is(DescribedPredicate.anyElementThat( + JavaCall.Predicates.target( + AccessTarget.Predicates.declaredIn("org.mockito.Mockito") + .and(HasName.Predicates.name("spy")) + ) + ))) + .should() + .beAssignableTo(BASE_IGNITE_ABSTRACT_TEST_CLASSNAME) + .as("Test classes, which use Mockito spies, must extends BaseIgniteAbstractTest") + .allowEmptyShould(true); +} diff --git a/modules/arch-test/src/test/java/org/apache/ignite/lang/TestsWithFixturesImportOption.java b/modules/arch-test/src/test/java/org/apache/ignite/lang/TestsWithFixturesImportOption.java new file mode 100644 index 0000000000..4954fde668 --- /dev/null +++ b/modules/arch-test/src/test/java/org/apache/ignite/lang/TestsWithFixturesImportOption.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.lang; + +import com.tngtech.archunit.core.importer.ImportOption; +import com.tngtech.archunit.core.importer.Location; +import java.util.regex.Pattern; + +/** + * Provide the ability to evaluate every class location, to determine if the class should be treated as a test fixture class. + */ +public class TestsWithFixturesImportOption implements ImportOption { + private static final Pattern fixturesTestPattern = Pattern.compile(".*/build/classes/([^/]+/)testFixtures/.*"); + private static final Pattern integrationTestPattern = Pattern.compile(".*/build/classes/([^/]+/)integrationTest/.*"); + + /** {@inheritDoc} */ + @Override + public boolean includes(Location location) { + return Predefined.ONLY_INCLUDE_TESTS.includes(location) + || location.matches(integrationTestPattern) + || location.matches(fixturesTestPattern); + } +}
