View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.junit;
16  
17  import java.util.ArrayList;
18  import java.util.Collections;
19  import java.util.List;
20  import java.util.Set;
21  
22  import org.htmlunit.BrowserVersion;
23  import org.htmlunit.WebDriverTestCase;
24  import org.htmlunit.WebTestCase;
25  import org.junit.runner.Runner;
26  import org.junit.runner.manipulation.Filter;
27  import org.junit.runner.manipulation.Filterable;
28  import org.junit.runner.manipulation.NoTestsRemainException;
29  import org.junit.runner.notification.RunNotifier;
30  import org.junit.runners.Suite;
31  import org.junit.runners.model.Statement;
32  
33  /**
34   * The custom runner <code>BrowserRunner</code> implements browser parameterized
35   * tests. When running a test class, instances are created for the
36   * cross-product of the test methods and {@link BrowserVersion}s.
37   *
38   * For example, write:
39   * <pre>
40   * &#064;RunWith(BrowserRunner.class)
41   * public class SomeTest extends WebTestCase {
42   *
43   *     &#064;Test
44   *     public void test() {
45   *         getBrowserVersion();// returns the currently used BrowserVersion
46   *     }
47   * }
48   * </pre>
49   *
50   * @author Ahmed Ashour
51   * @author Frank Danek
52   * @author Ronald Brill
53   * @author cd alexndr
54   */
55  public class BrowserRunner extends Suite {
56  
57      static final String REAL_CHROME = "chrome";
58      static final String REAL_FIREFOX = "ff";
59      static final String REAL_FIREFOX_ESR = "ff-esr";
60      static final String REAL_EDGE = "edge";
61  
62      static final String HTMLUNIT_CHROME = "hu-chrome";
63      static final String HTMLUNIT_FIREFOX = "hu-ff";
64      static final String HTMLUNIT_FIREFOX_ESR = "hu-ff-esr";
65      static final String HTMLUNIT_EDGE = "hu-edge";
66  
67      private final ArrayList<Runner> runners_ = new ArrayList<>();
68  
69      /**
70       * Constructor.
71       *
72       * @param klass the test case class
73       * @throws Throwable If an exception occurs
74       */
75      public BrowserRunner(final Class<WebTestCase> klass) throws Throwable {
76          super(klass, Collections.<Runner>emptyList());
77  
78          if (BrowserVersionClassRunner.containsTestMethods(klass)) {
79              final Set<String> browsers = WebDriverTestCase.getBrowsersProperties();
80              if (WebDriverTestCase.class.isAssignableFrom(klass)) {
81                  if (browsers.contains(REAL_CHROME)) {
82                      runners_.add(new BrowserVersionClassRunner(klass, BrowserVersion.CHROME, true));
83                  }
84                  if (browsers.contains(REAL_FIREFOX_ESR)) {
85                      runners_.add(new BrowserVersionClassRunner(klass, BrowserVersion.FIREFOX_ESR, true));
86                  }
87                  if (browsers.contains(REAL_FIREFOX)) {
88                      runners_.add(new BrowserVersionClassRunner(klass, BrowserVersion.FIREFOX, true));
89                  }
90                  if (browsers.contains(REAL_EDGE)) {
91                      runners_.add(new BrowserVersionClassRunner(klass, BrowserVersion.EDGE, true));
92                  }
93              }
94  
95              if (browsers.contains(HTMLUNIT_CHROME)) {
96                  runners_.add(new BrowserVersionClassRunner(klass, BrowserVersion.CHROME, false));
97              }
98              if (browsers.contains(HTMLUNIT_FIREFOX_ESR)) {
99                  runners_.add(new BrowserVersionClassRunner(klass, BrowserVersion.FIREFOX_ESR, false));
100             }
101             if (browsers.contains(HTMLUNIT_FIREFOX)) {
102                 runners_.add(new BrowserVersionClassRunner(klass, BrowserVersion.FIREFOX, false));
103             }
104             if (browsers.contains(HTMLUNIT_EDGE)) {
105                 runners_.add(new BrowserVersionClassRunner(klass, BrowserVersion.EDGE, false));
106             }
107         }
108         else {
109             throw new IllegalStateException("No @Test method found");
110         }
111     }
112 
113     @Override
114     protected Statement classBlock(final RunNotifier notifier) {
115         return childrenInvoker(notifier);
116     }
117 
118     /**
119      * {@inheritDoc}
120      */
121     @Override
122     public void filter(final Filter filter) throws NoTestsRemainException {
123         boolean atLeastOne = false;
124         for (final Runner runner : getChildren()) {
125             try {
126                 if (runner instanceof Filterable) {
127                     ((Filterable) runner).filter(filter);
128                     atLeastOne = true;
129                 }
130             }
131             catch (final NoTestsRemainException e) {
132                 // nothing
133             }
134         }
135 
136         if (!atLeastOne) {
137             throw new NoTestsRemainException();
138         }
139     }
140 
141     /**
142      * {@inheritDoc}
143      */
144     @Override
145     protected List<Runner> getChildren() {
146         return runners_;
147     }
148 
149     /**
150      * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br>
151      */
152     public static final String EMPTY_DEFAULT = "~InTerNal_To_BrowSeRRunNer#@$";
153 
154 }