View Javadoc

1   package com.atlassian.webdriver.testing.rule;
2   
3   import com.atlassian.webdriver.LifecycleAwareWebDriverGrid;
4   import org.junit.rules.TestWatcher;
5   import org.junit.runner.Description;
6   
7   import javax.annotation.concurrent.ThreadSafe;
8   import java.util.Iterator;
9   import java.util.Queue;
10  import java.util.Timer;
11  import java.util.TimerTask;
12  import java.util.concurrent.ConcurrentLinkedQueue;
13  import java.util.concurrent.TimeUnit;
14  
15  /**
16   * <p/>
17   * A class rule that cleans up web drivers from the {@link com.atlassian.webdriver.LifecycleAwareWebDriverGrid}
18   * after a specific amount of time elapses since the last test has been run.
19   *
20   * <p/>
21   * Some {@link org.openqa.selenium.WebDriver}s suffer from bugs that prevent shutdown hooks from cleaning them
22   * up properly. If you need to run your tests using those browsers (e.g. Chrome, IE), use this rule to
23   * make sure the browser will be closed after the test suite finishes.
24   *
25   * <p/>
26   * This rule is only effective if you use it in all your tests as a class rule. If you are using an injection context
27   * (e.g. a {@link com.atlassian.pageobjects.TestedProduct} with a {@link com.atlassian.pageobjects.PageBinder}),
28   * make sure this product's life cycle does not exceed this rule's life cycle (which is generally <code>true</code>,
29   * if you use a {@link com.atlassian.webdriver.testing.runner.ProductContextRunner}, or just manually instantiate
30   * the produce per test class).
31   *
32   * <p/>
33   * When instantiating the class clients can set a custom timeout, or use default constructor that sets a 3 seconds
34   * timeout.
35   *
36   * @since 2.1
37   */
38  @ThreadSafe
39  public class DriverCleanupRule extends TestWatcher
40  {
41  
42      private static final Timer KILLER_TIMER = new Timer("Atlassian-BrowserKiller", true);
43      private static final Queue<TimerTask> KILLER_TASKS = new ConcurrentLinkedQueue<TimerTask>();
44  
45      private final long timeout;
46      private final TimeUnit timeUnit;
47  
48      public DriverCleanupRule(long timeout, TimeUnit timeUnit)
49      {
50          this.timeout = timeout;
51          this.timeUnit = timeUnit;
52      }
53  
54      public DriverCleanupRule()
55      {
56          this(3, TimeUnit.SECONDS);
57      }
58  
59      @Override
60      protected void starting(Description description)
61      {
62          for (Iterator<TimerTask> tasks = KILLER_TASKS.iterator(); tasks.hasNext();)
63          {
64              tasks.next().cancel();
65              tasks.remove();
66          }
67      }
68  
69      @Override
70      protected void finished(Description description)
71      {
72          final TimerTask newKiller = new BrowserKiller();
73          KILLER_TASKS.add(newKiller);
74          KILLER_TIMER.schedule(newKiller, timeUnit.toMillis(timeout));
75      }
76  
77      private static final class BrowserKiller extends TimerTask
78      {
79  
80          @Override
81          public void run()
82          {
83              LifecycleAwareWebDriverGrid.shutdown();
84          }
85      }
86  }