Стандартный совет, способствовавший Yahoo! Исключительная команда Производительности, состоит в том, чтобы поместить теги в конце тела документа, таким образом, они не блокируют рендеринг страницы.
, Но существуют некоторые более новые подходы, которые предлагают лучшую производительность, как описано в этот ответ о времени загрузки файла Google Analytics JavaScript:
существуют [приблизительно 112] большие слайды Steve Souders (клиентский эксперт по производительности) о:
- Различные методы для загрузки внешних файлов JavaScript в параллели
- их эффект на время загрузки и страницу, представляющую
- , какой "в прогрессе" индикаторы дисплеи браузера (например, 'загружающуюся' в строке состояния, курсоре мыши песочных часов).
Решение Guerda хорошее. Вот что я в итоге сделал (это смесь рецепта Люка Франкла, на который я ссылался ранее, и некоторых других вещей, которые я видел в сети):
import org.junit.runner.manipulation.Filter;
import org.junit.runner.Description;
public final class AntCLFilter extends Filter {
private static final String TEST_CASES = "tests";
private static final String ANT_PROPERTY = "${tests}";
private static final String DELIMITER = "\\,";
private String[] testCaseNames;
public AntCLFilter() {
super();
if (hasTestCases()) testCaseNames = getTestCaseNames();
}
public String describe() {
return "Filters out all tests not explicitly named in a comma-delimited list in the system property 'tests'.";
}
public boolean shouldRun(Description d) {
String displayName = d.getDisplayName();
// cut off the method name:
String testName = displayName.substring(0, displayName.indexOf('('));
if (testCaseNames == null) return true;
for (int i = 0; i < testCaseNames.length; i++)
if (testName.equals(testCaseNames[i]))
return true;
return false;
}
/**
* Check to see if the test cases property is set. Ignores Ant's
* default setting for the property (or null to be on the safe side).
**/
public static boolean hasTestCases() {
return
System.getProperty( TEST_CASES ) == null ||
System.getProperty( TEST_CASES ).equals( ANT_PROPERTY ) ?
false : true;
}
/**
* Create a List of String names of test cases specified in the
* JVM property in comma-separated format.
*
* @return a List of String test case names
*
* @throws NullPointerException if the TEST_CASES property
* isn't set
**/
private static String[] getTestCaseNames() {
if ( System.getProperty( TEST_CASES ) == null ) {
throw new NullPointerException( "Test case property is not set" );
}
String testCases = System.getProperty( TEST_CASES );
String[] cases = testCases.split(DELIMITER);
return cases;
}
}
import org.junit.internal.runners.*;
import org.junit.runner.manipulation.Filter;
import org.junit.runner.manipulation.NoTestsRemainException;
public class FilteredRunner extends TestClassRunner {
public FilteredRunner(Class<?> clazz) throws InitializationError {
super(clazz);
Filter f = new AntCLFilter();
try {
f.apply(this);
} catch (NoTestsRemainException ex) {
throw new RuntimeException(ex);
}
}
}
Затем я аннотировал свой тестовый класс с помощью:
@RunWith(FilteredRunner.class)
public class MyTest {
и поместил следующее в мой файл сборки ant:
<target name="runtest"
description="Runs the test you specify on the command line with -Dtest="
depends="compile, ensure-test-name">
<junit printsummary="withOutAndErr" fork="yes">
<sysproperty key="tests" value="${tests}" />
<classpath refid="classpath" />
<formatter type="plain" usefile="false" />
<batchtest>
<fileset dir="${src}">
<include name="**/${test}.java" />
</fileset>
</batchtest>
</junit>
</target>
ключевая строка, содержащая тег sysproperty.
И теперь я могу запустить
ant runtest -Dtest=MyTest -Dtests=testFoo,testBar
по своему желанию. Это работает с JUnit 4.1 --- в 4.4, подклассом от JUnit4ClassRunner, и в 4.5 и новее, подклассом от BlockJUnit4ClassRunner.
Создайте свой собственный TestClassMethodsRunner
(он не задокументирован или я не нахожу его сейчас).
TestClassMethodsRunner
выполняет все TestCases, и вы можете настроить отфильтрованный TestClassMethodsRunner
.
Все, что вам нужно сделать, это переопределить TestMethodRunner createMethodRunner (ObjectNo 1121405] метод. Это простое хакерское решение:
public class FilteredTestRunner extends TestClassMethodsRunner {
public FilteredTestRunner(Class<?> aClass) {
super(aClass);
}
@Override
protected TestMethodRunner createMethodRunner(Object aTest, Method aMethod, RunNotifier aNotifier) {
if (aTest.getClass().getName().contains("NOT")) {
return new TestMethodRunner(aTest, aMethod, aNotifier, null) {
@Override
public void run() {
//do nothing with this test.
}
};
} else {
return super.createMethodRunner(aTest, aMethod, aNotifier);
}
}
}
С помощью этого TestRunner вы выполняете все тесты, которые не содержат строку «NOT». Остальные будут проигнорированы :) Просто добавьте аннотацию @RunWith
с вашим классом TestRunner в свой тест.
@RunWith(FilteredTestRunner.class)
public class ThisTestsWillNOTBeExecuted {
//No test is executed.
}
@RunWith(FilteredTestRunner.class)
public class ThisTestsWillBeExecuted {
//All tests are executed.
}
В методе createMethodRunner
вы можете проверить текущий тест по списку тестов которые необходимо выполнить, или ввести новые критерии.
Удачи!
Подсказки для лучшего решения приветствуются!