Skip to content

Commit 113ca7e

Browse files
Merge pull request #203 from telekom/feature/tt2-loopdetection
Feature/tt2 loopdetection
2 parents 8c897a0 + e4107c9 commit 113ca7e

File tree

3 files changed

+117
-42
lines changed

3 files changed

+117
-42
lines changed

driver-ui/src/main/java/eu/tsystems/mms/tic/testframework/pageobjects/internal/DefaultPageFactory.java

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,34 @@
2020
*/
2121
package eu.tsystems.mms.tic.testframework.pageobjects.internal;
2222

23+
import com.google.common.eventbus.EventBus;
24+
import com.google.common.eventbus.Subscribe;
25+
import eu.tsystems.mms.tic.testframework.common.Testerra;
2326
import eu.tsystems.mms.tic.testframework.enums.CheckRule;
27+
import eu.tsystems.mms.tic.testframework.events.MethodEndEvent;
2428
import eu.tsystems.mms.tic.testframework.exceptions.PageFactoryException;
2529
import eu.tsystems.mms.tic.testframework.logging.Loggable;
2630
import eu.tsystems.mms.tic.testframework.pageobjects.Component;
2731
import eu.tsystems.mms.tic.testframework.pageobjects.Page;
2832
import eu.tsystems.mms.tic.testframework.pageobjects.UiElement;
29-
import eu.tsystems.mms.tic.testframework.utils.StringUtils;
30-
import java.lang.reflect.Constructor;
33+
import org.apache.commons.collections.buffer.CircularFifoBuffer;
34+
import org.apache.commons.lang3.StringUtils;
3135
import org.openqa.selenium.WebDriver;
3236

33-
public class DefaultPageFactory implements PageFactory, Loggable {
37+
import java.lang.reflect.Constructor;
38+
import java.util.List;
39+
import java.util.stream.Collectors;
40+
41+
public class DefaultPageFactory implements PageFactory, MethodEndEvent.Listener, Loggable {
3442

3543
@Deprecated
3644
private String GLOBAL_PAGES_PREFIX = null;
3745
@Deprecated
3846
private final ThreadLocal<String> THREAD_LOCAL_PAGES_PREFIX = new ThreadLocal<>();
3947

48+
private static final ThreadLocal<CircularFifoBuffer> LOOP_DETECTION_LOGGER = new ThreadLocal<>();
49+
private static final int NR_OF_LOOPS = Properties.PAGE_FACTORY_LOOPS.asLong().intValue();
50+
4051
@Override
4152
public PageFactory setGlobalPagesPrefix(String pagePrefix) {
4253
GLOBAL_PAGES_PREFIX = pagePrefix;
@@ -55,25 +66,31 @@ public PageFactory clearThreadLocalPagesPrefix() {
5566
return this;
5667
}
5768

69+
public DefaultPageFactory() {
70+
// For clear PageFactory loop detection buffer
71+
EventBus eventBus = Testerra.getEventBus();
72+
eventBus.register(this);
73+
}
74+
5875
@Override
5976
public <T extends Page> T createPage(Class<T> pageClass, WebDriver webDriver) {
6077
return createPageWithCheckRule(pageClass, webDriver, CheckRule.DEFAULT);
6178
}
6279

6380
private String getConfiguredPrefix() {
6481
String pagesPrefix = GLOBAL_PAGES_PREFIX;
65-
if (!StringUtils.isStringEmpty(THREAD_LOCAL_PAGES_PREFIX.get())) {
82+
if (StringUtils.isNotEmpty(THREAD_LOCAL_PAGES_PREFIX.get())) {
6683
pagesPrefix = THREAD_LOCAL_PAGES_PREFIX.get();
6784
}
68-
return (pagesPrefix!=null?pagesPrefix:"");
85+
return (pagesPrefix != null ? pagesPrefix : "");
6986
}
7087

7188
@Override
7289
public <T extends Component> T createComponent(Class<T> componentClass, UiElement rootElement) {
7390
try {
7491
Constructor<T> constructor = componentClass.getConstructor(UiElement.class);
7592
T component = constructor.newInstance(rootElement);
76-
((AbstractPage)component).checkUiElements();
93+
((AbstractPage) component).checkUiElements();
7794
return component;
7895
} catch (Throwable throwable) {
7996
throw new PageFactoryException(componentClass, rootElement.getWebDriver(), throwable);
@@ -83,16 +100,50 @@ public <T extends Component> T createComponent(Class<T> componentClass, UiElemen
83100
@Override
84101
@Deprecated
85102
public <T extends Page> T createPageWithCheckRule(Class<T> pageClass, WebDriver webDriver, CheckRule checkRule) {
103+
T page;
86104
try {
87-
String pageClassString = String.format("%s.%s%s",pageClass.getPackage().getName(), getConfiguredPrefix(), pageClass.getSimpleName());
105+
String pageClassString = String.format("%s.%s%s", pageClass.getPackage().getName(), getConfiguredPrefix(), pageClass.getSimpleName());
88106
pageClass = (Class<T>) Class.forName(pageClassString);
89107

90108
Constructor<T> constructor = pageClass.getConstructor(WebDriver.class);
91-
T page = constructor.newInstance(webDriver);
92-
((AbstractPage)page).checkUiElements(checkRule);
93-
return page;
109+
page = constructor.newInstance(webDriver);
110+
((AbstractPage) page).checkUiElements(checkRule);
94111
} catch (Throwable throwable) {
95112
throw new PageFactoryException(pageClass, webDriver, throwable);
96113
}
114+
this.runLoopDetection(pageClass);
115+
return page;
116+
}
117+
118+
private void runLoopDetection(Class pageClass) {
119+
CircularFifoBuffer buffer = LOOP_DETECTION_LOGGER.get();
120+
if (buffer == null) {
121+
CircularFifoBuffer fifoBuffer = new CircularFifoBuffer(NR_OF_LOOPS);
122+
LOOP_DETECTION_LOGGER.set(fifoBuffer);
123+
buffer = LOOP_DETECTION_LOGGER.get();
124+
}
125+
126+
buffer.add(pageClass);
127+
128+
// Check if complete buffer contains only one class
129+
if (buffer.size() == NR_OF_LOOPS) {
130+
List<Class> list = (List<Class>) buffer.stream().distinct().collect(Collectors.toList());
131+
132+
// if this list is size 1, then there is only 1 page type loaded in NR_OF_LOOPS load actions (recorded by the buffer)
133+
if (list.size() == 1) {
134+
// NR_OF_LOOPS times this one class has been loaded in this thread
135+
throw new RuntimeException("PageFactory create loop detected loading: " + list.get(0));
136+
}
137+
}
138+
}
139+
140+
@Override
141+
@Subscribe
142+
public void onMethodEnd(MethodEndEvent event) {
143+
this.clearLoopDetectionBuffer();
144+
}
145+
146+
private void clearLoopDetectionBuffer() {
147+
LOOP_DETECTION_LOGGER.get().clear();
97148
}
98149
}

driver-ui/src/main/java/eu/tsystems/mms/tic/testframework/pageobjects/internal/PageFactory.java

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,30 +21,55 @@
2121

2222
package eu.tsystems.mms.tic.testframework.pageobjects.internal;
2323

24+
import eu.tsystems.mms.tic.testframework.common.IProperties;
2425
import eu.tsystems.mms.tic.testframework.enums.CheckRule;
25-
import eu.tsystems.mms.tic.testframework.exceptions.PageFactoryException;
2626
import eu.tsystems.mms.tic.testframework.logging.Loggable;
2727
import eu.tsystems.mms.tic.testframework.pageobjects.Component;
2828
import eu.tsystems.mms.tic.testframework.pageobjects.Page;
2929
import eu.tsystems.mms.tic.testframework.pageobjects.UiElement;
3030
import eu.tsystems.mms.tic.testframework.testing.TestControllerProvider;
3131
import eu.tsystems.mms.tic.testframework.testing.WebDriverManagerProvider;
32+
import org.openqa.selenium.WebDriver;
33+
3234
import java.util.Optional;
3335
import java.util.concurrent.atomic.AtomicReference;
34-
import org.checkerframework.checker.units.qual.A;
35-
import org.openqa.selenium.WebDriver;
3636

3737
public interface PageFactory extends WebDriverManagerProvider, TestControllerProvider, Loggable {
3838
@Deprecated
3939
PageFactory setGlobalPagesPrefix(String pagePrefix);
40+
4041
@Deprecated
4142
PageFactory setThreadLocalPagesPrefix(String pagePrefix);
43+
4244
@Deprecated
4345
PageFactory clearThreadLocalPagesPrefix();
4446

47+
enum Properties implements IProperties {
48+
PAGE_FACTORY_LOOPS("tt.page.factory.loops", 20);
49+
50+
private final String property;
51+
private final Object defaultValue;
52+
53+
Properties(String property, Object defaultValue) {
54+
this.property = property;
55+
this.defaultValue = defaultValue;
56+
}
57+
58+
@Override
59+
public String toString() {
60+
return property;
61+
}
62+
63+
@Override
64+
public Object getDefault() {
65+
return defaultValue;
66+
}
67+
}
68+
4569
default <T extends Page> T createPage(Class<T> pageClass) {
4670
return createPage(pageClass, WEB_DRIVER_MANAGER.getWebDriver());
4771
}
72+
4873
<T extends Page> T createPage(Class<T> pageClass, WebDriver webDriver);
4974

5075
default <T extends Page> Optional<T> waitForPage(Class<T> pageClass, int seconds) {

integration-tests/src/test/java/eu/tsystems/mms/tic/testframework/test/pagefactory/PageFactoryTest.java

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,9 @@
2929
import eu.tsystems.mms.tic.testframework.core.pageobjects.testdata.GuiElementListPage;
3030
import eu.tsystems.mms.tic.testframework.core.pageobjects.testdata.PageWithExistingElement;
3131
import eu.tsystems.mms.tic.testframework.pageobjects.Page;
32-
import eu.tsystems.mms.tic.testframework.pageobjects.factory.PageFactory;
3332
import eu.tsystems.mms.tic.testframework.report.Report;
3433
import eu.tsystems.mms.tic.testframework.report.TesterraListener;
35-
import eu.tsystems.mms.tic.testframework.webdrivermanager.WebDriverManager;
34+
import eu.tsystems.mms.tic.testframework.testing.PageFactoryProvider;
3635
import org.openqa.selenium.WebDriver;
3736
import org.testng.Assert;
3837
import org.testng.annotations.DataProvider;
@@ -44,7 +43,7 @@
4443
/**
4544
* Tests the responsive page factory for correct instantiated classes.
4645
*/
47-
public class PageFactoryTest extends AbstractTestSitesTest {
46+
public class PageFactoryTest extends AbstractTestSitesTest implements PageFactoryProvider {
4847

4948
@Test
5049
public void test_pageLoadedCallback() {
@@ -85,29 +84,29 @@ public void testT08_CheckPage_ScreenshotOnLoad() {
8584
Assert.assertNotEquals(fileCountAfterCheckPageWithoutScreenshot, fileCountAfterCheckPageWithScreenshot, "Record Screenshot count altered.");
8685
}
8786

88-
// @Test(expectedExceptions = RuntimeException.class, expectedExceptionsMessageRegExp = "PageFactory create loop detected loading.*")
89-
// public void testT10_LoopDetectionTest_Exception() {
90-
// WebDriver driver = WebDriverManager.getWebDriver();
91-
// for (int i = 0; i < 6; i++) {
92-
// PageFactory.create(GuiElementListPage.class, driver);
93-
// }
94-
// }
95-
//
96-
// @Test()
97-
// public void testT11_LoopDetectionTest_Passed() {
98-
// WebDriver driver = WebDriverManager.getWebDriver();
99-
// for (int i = 0; i < 6; i++) {
100-
// PageFactory.create(GuiElementListPage.class, driver);
101-
// PageFactory.create(BasePage.class, driver);
102-
// }
103-
// }
104-
//
105-
// @DataProvider(name = "LoopDetectionInDataProvider", parallel = false)
106-
// public Object[][] testT12_Dataprovider() {
107-
// return new Object[][]{
108-
// {"Test_1"}, {"Test_2"}, {"Test_3"}
109-
// };
110-
// }
87+
@Test(expectedExceptions = RuntimeException.class, expectedExceptionsMessageRegExp = "PageFactory create loop detected loading.*")
88+
public void testT10_LoopDetectionTest_Exception() {
89+
WebDriver driver = getWebDriver();
90+
for (int i = 0; i < 6; i++) {
91+
PAGE_FACTORY.createPage(PageWithExistingElement.class, driver);
92+
}
93+
}
94+
95+
@Test()
96+
public void testT11_LoopDetectionTest_Passed() {
97+
WebDriver driver = getWebDriver();
98+
for (int i = 0; i < 6; i++) {
99+
PAGE_FACTORY.createPage(GuiElementListPage.class, driver);
100+
PAGE_FACTORY.createPage(BasePage.class, driver);
101+
}
102+
}
103+
104+
@DataProvider(name = "LoopDetectionInDataProvider", parallel = false)
105+
public Object[][] testT12_Dataprovider() {
106+
return new Object[][]{
107+
{"Test_1"}, {"Test_2"}
108+
};
109+
}
111110

112111
/**
113112
* PageFactory loop detection buffer is cleared after every method
@@ -116,9 +115,9 @@ public void testT08_CheckPage_ScreenshotOnLoad() {
116115
*/
117116
@Test(dataProvider = "LoopDetectionInDataProvider")
118117
public void testT12_LoopDetectionTest_DataProvider_ParallelFalse(String loop) {
119-
WebDriver driver = WebDriverManager.getWebDriver();
120-
for (int i = 0; i < 2; i++) {
121-
PageFactory.create(BasePage.class, driver);
118+
WebDriver driver = getWebDriver();
119+
for (int i = 0; i < 4; i++) {
120+
PAGE_FACTORY.createPage(BasePage.class, driver);
122121
}
123122
}
124123

0 commit comments

Comments
 (0)