{"action":"created","issue":{"url":"https://api.github.com/repos/cbeust/testng/issues/1726","repository_url":"https://api.github.com/repos/cbeust/testng","labels_url":"https://api.github.com/repos/cbeust/testng/issues/1726/labels{/name}","comments_url":"https://api.github.com/repos/cbeust/testng/issues/1726/comments","events_url":"https://api.github.com/repos/cbeust/testng/issues/1726/events","html_url":"https://github.com/cbeust/testng/issues/1726","id":307111999,"number":1726,"title":"Need a way to exclude built-in interceptors from being added to alter method order","user":{"login":"krmahadevan","id":909773,"avatar_url":"https://avatars0.githubusercontent.com/u/909773?v=4","gravatar_id":"","url":"https://api.github.com/users/krmahadevan","html_url":"https://github.com/krmahadevan","followers_url":"https://api.github.com/users/krmahadevan/followers","following_url":"https://api.github.com/users/krmahadevan/following{/other_user}","gists_url":"https://api.github.com/users/krmahadevan/gists{/gist_id}","starred_url":"https://api.github.com/users/krmahadevan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/krmahadevan/subscriptions","organizations_url":"https://api.github.com/users/krmahadevan/orgs","repos_url":"https://api.github.com/users/krmahadevan/repos","events_url":"https://api.github.com/users/krmahadevan/events{/privacy}","received_events_url":"https://api.github.com/users/krmahadevan/received_events","type":"User","site_admin":false},"labels":[{"id":230596133,"url":"https://api.github.com/repos/cbeust/testng/labels/Feature:%20interceptor","name":"Feature: interceptor","color":"0e8a16","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-03-21T03:47:27Z","updated_at":"2018-03-21T03:49:18Z","closed_at":null,"author_association":"COLLABORATOR","body":"### TestNG Version\r\n> Note: only the latest version is supported\r\n6.14.3\r\n\r\n### Expected behavior\r\nThe method order as determined by user provided method interceptor should be the order in which tests are executed.\r\n\r\n### Actual behavior\r\n\r\nThe method order gets changed based on the outcome of the built-in interceptor that TestNG injects finally (Currently its either `org.testng.PreserveOrderMethodInterceptor` when `preserve-order=true` or `org.testng.InstanceOrderingMethodInterceptor` when `preserve-order=false`)\r\n\r\n### Is the issue reproductible on runner?\r\n\r\n- [X] Shell\r\n- [X] Maven\r\n- [X] Gradle\r\n- [X] Ant\r\n- [X] Eclipse\r\n- [X] IntelliJ\r\n- [X] NetBeans\r\n\r\n\r\n### Test case sample\r\n> Please, share the test case (as small as possible) which shows the issue\r\n\r\n**Test classes**\r\n\r\n```java\r\nimport org.testng.annotations.Test;\r\nimport priority.Priority;\r\n\r\npublic class TestClass1 {\r\n\r\n    @Priority(4)\r\n    @Test(description = \"Test Multiple Day Absence Request flow\", groups = \"Test\")\r\n    public void Test1() {\r\n        System.out.println(getClass().getName() + \".Test1\");\r\n    }\r\n\r\n    @Priority(8)\r\n    @Test(description = \"Test Single Day Absence Request Flow\", groups = {\"Regression\", \"Test\"})\r\n    public void Test2() {\r\n        System.out.println(getClass().getName() + \".Test2\");\r\n    }\r\n}\r\n```\r\n\r\n```java\r\nimport org.testng.annotations.Test;\r\nimport priority.Priority;\r\n\r\npublic class TestClass2 {\r\n\r\n    @Priority(3)\r\n    @Test(description = \"Test Multiple Day Absence Request flow\", groups = \"Test\")\r\n    public void Test3() {\r\n        System.out.println(getClass().getName() + \".Test3\");\r\n    }\r\n\r\n    @Priority(9)\r\n    @Test(description = \"Test Single Day Absence Request Flow\", groups = {\"Regression\", \"Test\"})\r\n    public void Test4() {\r\n        System.out.println(getClass().getName() + \".Test4\");\r\n    }\r\n}\r\n```\r\n\r\nCustom annotation looks like below:\r\n\r\n```java\r\nimport java.lang.annotation.ElementType;\r\nimport java.lang.annotation.Retention;\r\nimport java.lang.annotation.Target;\r\n\r\n@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)\r\n@Target({ElementType.METHOD, ElementType.TYPE})\r\npublic @interface Priority {\r\n    int value() default 0;\r\n}\r\n```\r\n\r\nCustom interceptor looks like below:\r\n\r\n```java\r\nimport org.testng.IMethodInstance;\r\nimport org.testng.IMethodInterceptor;\r\nimport org.testng.ITestContext;\r\n\r\nimport java.lang.reflect.Method;\r\nimport java.util.ArrayList;\r\nimport java.util.Comparator;\r\nimport java.util.List;\r\n\r\npublic class PriorityInterceptor implements IMethodInterceptor {\r\n    public static List<String> ordered = new ArrayList<>();\r\n\r\n    public List<IMethodInstance> intercept(List<IMethodInstance> methods,\r\n                                           ITestContext context) {\r\n        Comparator<IMethodInstance> comparator = new Comparator<IMethodInstance>() {\r\n\r\n            private int getPriority(IMethodInstance mi) {\r\n                int result = 0;\r\n                Method method = mi.getMethod().getConstructorOrMethod().getMethod();\r\n                Priority a1 = method.getAnnotation(Priority.class);\r\n                if (a1 != null) {\r\n                    result = a1.value();\r\n                } else {\r\n                    Class<?> cls = method.getDeclaringClass();\r\n                    Priority classPriority = cls.getAnnotation(Priority.class);\r\n                    if (classPriority != null) {\r\n                        result = classPriority.value();\r\n                    }\r\n                }\r\n                return result;\r\n            }\r\n\r\n            public int compare(IMethodInstance m1, IMethodInstance m2) {\r\n                return getPriority(m1) - getPriority(m2);\r\n            }\r\n\r\n        };\r\n        methods.sort(comparator);\r\n        methods.forEach(m -> {\r\n            String clazz = m.getMethod().getInstance().getClass().getName() + \".\";\r\n            ordered.add(clazz + m.getMethod().getMethodName());\r\n        });\r\n        return methods;\r\n    }\r\n\r\n}\r\n```\r\n\r\nHere's how the test runner looks like\r\n\r\n```java\r\nimport org.testng.Assert;\r\nimport org.testng.IInvokedMethod;\r\nimport org.testng.IInvokedMethodListener;\r\nimport org.testng.ITestNGListener;\r\nimport org.testng.ITestResult;\r\nimport org.testng.TestNG;\r\nimport org.testng.annotations.Test;\r\nimport priority.PriorityInterceptor;\r\n\r\nimport java.util.ArrayList;\r\nimport java.util.Arrays;\r\nimport java.util.List;\r\n\r\npublic class TestRunner {\r\n    @Test\r\n    public void testMethod() {\r\n        TestNG testng = new TestNG();\r\n        testng.setTestClasses(new Class[]{TestClass1.class, TestClass2.class});\r\n        testng.addListener(new PriorityInterceptor());\r\n        testng.addListener((ITestNGListener) new MethodOrderTracker());\r\n        testng.run();\r\n        List<String> expected = Arrays.asList(\r\n                \"scenarios.TestClass2.Test3\",\r\n                \"scenarios.TestClass1.Test1\",\r\n                \"scenarios.TestClass1.Test2\",\r\n                \"scenarios.TestClass2.Test4\"\r\n        );\r\n        Assert.assertEquals(MethodOrderTracker.ordered, expected);\r\n    }\r\n\r\n    public static class MethodOrderTracker implements IInvokedMethodListener {\r\n        static List<String> ordered = new ArrayList<>();\r\n\r\n        @Override\r\n        public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {\r\n\r\n        }\r\n\r\n        @Override\r\n        public void afterInvocation(IInvokedMethod method, ITestResult testResult) {\r\n            String clazz = method.getTestMethod().getRealClass().getName() + \".\";\r\n            ordered.add(clazz + method.getTestMethod().getMethodName());\r\n        }\r\n    }\r\n}\r\n```\r\n\r\nCurrently the test runner is failing."},"comment":{"url":"https://api.github.com/repos/cbeust/testng/issues/comments/374827450","html_url":"https://github.com/cbeust/testng/issues/1726#issuecomment-374827450","issue_url":"https://api.github.com/repos/cbeust/testng/issues/1726","id":374827450,"user":{"login":"krmahadevan","id":909773,"avatar_url":"https://avatars0.githubusercontent.com/u/909773?v=4","gravatar_id":"","url":"https://api.github.com/users/krmahadevan","html_url":"https://github.com/krmahadevan","followers_url":"https://api.github.com/users/krmahadevan/followers","following_url":"https://api.github.com/users/krmahadevan/following{/other_user}","gists_url":"https://api.github.com/users/krmahadevan/gists{/gist_id}","starred_url":"https://api.github.com/users/krmahadevan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/krmahadevan/subscriptions","organizations_url":"https://api.github.com/users/krmahadevan/orgs","repos_url":"https://api.github.com/users/krmahadevan/repos","events_url":"https://api.github.com/users/krmahadevan/events{/privacy}","received_events_url":"https://api.github.com/users/krmahadevan/received_events","type":"User","site_admin":false},"created_at":"2018-03-21T03:49:18Z","updated_at":"2018-03-21T03:49:18Z","author_association":"COLLABORATOR","body":"ping @cbeust @juherr - Need your inputs on this. Should we support a use case wherein we let users wire off the **in-built** interceptors if they choose to ?\r\n\r\nThis bug is being filed on behalf of the user as a result of [this](https://groups.google.com/forum/#!topic/testng-users/cSP4QpVGxMQ) google forum thread "}}
{"actor":{"display_login":"krmahadevan"}}