diff --git a/src/main/java/com/zebrunner/carina/core/registrar/ownership/MethodOwner.java b/src/main/java/com/zebrunner/carina/core/registrar/ownership/MethodOwner.java
index 0f2257bd3..9d6a634fe 100644
--- a/src/main/java/com/zebrunner/carina/core/registrar/ownership/MethodOwner.java
+++ b/src/main/java/com/zebrunner/carina/core/registrar/ownership/MethodOwner.java
@@ -22,13 +22,19 @@
import java.lang.annotation.Target;
/**
- * This defines the 'MethodOwner' annotation used to specify the
- * TestNG methods owners.
- *
+ * Allows to specify the owner of the test method/test class.
+ * The order of priorities when choosing the owner of the test method:
+ * 1. The annotation on a test method containing a suitable plaftorm.
+ * 2. The annotation on a test class containing a suitable platform.
+ * 3. The annotation on a test method without the specified platform.
+ * 4 The annotation on a test class withot the specified platform.
+ *
+ *
+ * The expected platform is determined based on the "capabilities.platformName" in the {@link com.zebrunner.carina.utils.R#CONFIG} (case-insensitive).
*/
@Repeatable(MethodOwner.List.class)
@Retention(value = RetentionPolicy.RUNTIME)
-@Target(value = ElementType.METHOD)
+@Target(value = { ElementType.METHOD, ElementType.TYPE })
public @interface MethodOwner {
String owner() default "";
diff --git a/src/main/java/com/zebrunner/carina/core/registrar/ownership/Ownership.java b/src/main/java/com/zebrunner/carina/core/registrar/ownership/Ownership.java
index e7d838714..ed5dc3a9d 100644
--- a/src/main/java/com/zebrunner/carina/core/registrar/ownership/Ownership.java
+++ b/src/main/java/com/zebrunner/carina/core/registrar/ownership/Ownership.java
@@ -15,67 +15,111 @@
*******************************************************************************/
package com.zebrunner.carina.core.registrar.ownership;
+import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
+import java.util.Optional;
+
+import org.openqa.selenium.remote.CapabilityType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
-import com.zebrunner.carina.utils.Configuration;
import com.zebrunner.agent.core.registrar.maintainer.MaintainerResolver;
-import org.apache.commons.lang3.StringUtils;
+import com.zebrunner.carina.utils.R;
public class Ownership implements MaintainerResolver {
+ // todo think about adding validation for the platform duplicates in method/class annotations
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ // todo move to AbstractCapabilities
+ private static final String CAPABILITIES_CONFIG_PREFIX = "capabilities.";
@Override
public String resolve(Class> clazz, Method method) {
- String owner = StringUtils.EMPTY;
- // Get a handle to the class and method
- // We can't use getMethod() because we may have parameterized tests
- // for which we don't know the matching signature
- String methodName = method.getName();
- Method testMethod = null;
- Method[] possibleMethods = clazz.getMethods();
- for (Method possibleMethod : possibleMethods) {
- if (possibleMethod.getName().equals(methodName)) {
- testMethod = possibleMethod;
- break;
- }
- }
-
- // do a scan for single Methodowner annotation as well)
- if (testMethod != null && testMethod.isAnnotationPresent(MethodOwner.class)) {
- MethodOwner methodAnnotation = testMethod.getAnnotation(MethodOwner.class);
- owner = methodAnnotation.owner();
+ // In order not to check for null further
+ if (method == null || clazz == null) {
+ return null;
}
-
- // scan all MethodOwner annotations to find default ownership without any platform
- if (testMethod != null && testMethod.isAnnotationPresent(MethodOwner.List.class)) {
- MethodOwner.List methodAnnotation = testMethod.getAnnotation(MethodOwner.List.class);
- for (MethodOwner methodOwner : methodAnnotation.value()) {
- String actualPlatform = methodOwner.platform();
- if (actualPlatform.isEmpty()) {
- owner = methodOwner.owner();
- break;
- }
+
+ String expectedPlatform = R.CONFIG.get(CAPABILITIES_CONFIG_PREFIX + CapabilityType.PLATFORM_NAME);
+ Optional possibleMethodOwner = getMethodOwner(method, expectedPlatform);
+ Optional possibleClassOwner = getClassOwner(clazz, expectedPlatform);
+
+ // resolve platform-specific method owner
+ if (possibleMethodOwner.isPresent()) {
+ MethodOwner methodOwner = possibleMethodOwner.get();
+ if (!methodOwner.platform().isEmpty()) {
+ return methodOwner.owner();
}
}
-
- //do one more scan using platform ownership filter if any to override default owner value
- if (testMethod != null && testMethod.isAnnotationPresent(MethodOwner.List.class)) {
- MethodOwner.List methodAnnotation = testMethod.getAnnotation(MethodOwner.List.class);
- for (MethodOwner methodOwner : methodAnnotation.value()) {
- String actualPlatform = methodOwner.platform();
- String expectedPlatform = Configuration.getPlatform();
-
- if (!actualPlatform.isEmpty() && isValidPlatform(actualPlatform, expectedPlatform)) {
- owner = methodOwner.owner();
- }
+ // resolve platform-specific class owner
+ if (possibleClassOwner.isPresent()) {
+ MethodOwner classOwner = possibleClassOwner.get();
+ if (!classOwner.platform().isEmpty()) {
+ return classOwner.owner();
}
}
- return owner;
+ String suitableAnyPlatformOwner = null;
+ // resolve all-other-platforms method/class owner
+ if (possibleMethodOwner.isPresent()) {
+ suitableAnyPlatformOwner = possibleMethodOwner.get().owner();
+ } else if (possibleClassOwner.isPresent()) {
+ suitableAnyPlatformOwner = possibleClassOwner.get().owner();
+ }
+
+ return suitableAnyPlatformOwner;
}
-
- private static boolean isValidPlatform(String actualPlatform, String expectedPlatform) {
- return actualPlatform.equalsIgnoreCase(expectedPlatform);
+
+ /**
+ * Get suitable method owner
+ *
+ * @param method test method
+ * @param expectedPlatform expected platform
+ * @return {@link Optional} of {@link MethodOwner}
+ */
+ private static Optional getMethodOwner(Method method, String expectedPlatform) {
+ Optional suitableMethodOwner = Optional.empty();
+ if (method.isAnnotationPresent(MethodOwner.class)) {
+ MethodOwner[] owners = new MethodOwner[1];
+ owners[0] = method.getAnnotation(MethodOwner.class);
+ suitableMethodOwner = getOwner(owners, expectedPlatform);
+ } else if (method.isAnnotationPresent(MethodOwner.List.class)) {
+ suitableMethodOwner = getOwner(method.getAnnotation(MethodOwner.List.class).value(), expectedPlatform);
+ }
+ return suitableMethodOwner;
+ }
+
+ /**
+ * Get suitable class owner
+ *
+ * @param clazz test class
+ * @param expectedPlatform expected platform
+ * @return {@link Optional} of {@link MethodOwner}
+ */
+ private static Optional getClassOwner(Class> clazz, String expectedPlatform) {
+ Optional suitableMethodOwner = Optional.empty();
+ if (clazz.isAnnotationPresent(MethodOwner.class)) {
+ MethodOwner[] owners = new MethodOwner[1];
+ owners[0] = clazz.getAnnotation(MethodOwner.class);
+ suitableMethodOwner = getOwner(owners, expectedPlatform);
+ } else if (clazz.isAnnotationPresent(MethodOwner.List.class)) {
+ suitableMethodOwner = getOwner(clazz.getAnnotation(MethodOwner.List.class).value(), expectedPlatform);
+ }
+ return suitableMethodOwner;
}
-}
\ No newline at end of file
+ private static Optional getOwner(MethodOwner[] owners, String expectedPlatform) {
+ MethodOwner suitableOwner = null;
+ for (MethodOwner owner : owners) {
+ if (owner.platform().isEmpty()) {
+ suitableOwner = owner;
+ } else if (owner.platform().equalsIgnoreCase(expectedPlatform)) {
+ suitableOwner = owner;
+ // If an annotation was found suitable for a specific platform, there is no point in continuing to search further.
+ break;
+ }
+ }
+ return Optional.ofNullable(suitableOwner);
+ }
+}