TeamCity поддерживает jUnit «на лету» и особых проблем с выполнением тестов нет. Но стандартная поддержка не покрывает все юзкейсы. Например, никогда нельзя быть уверенным, в какой очередности пройдут тесты. Кроме того, есть другие вариации тестовой архитектуры, которые просто невозможно сделать дефолтными средствами jUnit. Например, определение в рантайме, какие тесты нужно запускать, а какие нет. Причем с выводом в отчетах в TeamCity без проигнорированных тестов.
Это иногда действительно смущает. У меня была ситуация, когда были написаны тесты для тестирования веб-сервера и все работало хорошо. Но как-то сам веб-сервер упал (в тестах не было логики по остановке / запуску веб-сервера), но часть тестов в репортах TeamCity были отмечены как успешные (так отмечаются в списке все проигнорированные). Естественно заказчик сказал «What the...».
Вроде бы ничего сложного — использовать сервисные сообщения TeamCity. Но в TeamCity есть официальная бага, при которой сервисные сообщения в TestOutput не читаются.
1. Вывод сообщений
Для удобства создадим кастомный класс для вывода сообщений. Чтобы передать команду в TeamCity, необходимо отправить ее в стандартный out поток.
public class Log
{
public static void logTCTestSuiteStart( String message )
{
System.out.println( "##teamcity[testSuiteStarted name='" + message + "']" );
}
public static void logTCTestSuiteFinished( String message )
{
System.out.println( "##teamcity[testSuiteFinished name='" + message + "']" );
}
public static void logTCTestStart( String message )
{
System.out.println( "##teamcity[testStarted name='" + message + "']" );
}
public static void logTCTestFinished( String message )
{
System.out.println( "##teamcity[testFinished name='" + message + "']" );
}
public static void logTCTestFailed( String message, AssertionError e )
{
System.out.println(
"##teamcity[testFailed name='" + message + "' message='" + e.getMessage() + "']" );
}
}
Каждая группа тестов должна быть размещена в блоке TestSuite, используя команды 'testSuiteStarted' и 'testSuiteFinished'. Каждый тест должен начинаться с 'testStarted' и заканчиваться с 'testFinished'. Тест будет считаться успешным, если внутри тестового блока не будет команды 'testFailed'.
Более подробно о поддерживаемых сервисных сообщениях в TeamCity можно почитать тут.
2. Простой тест
Теперь мы можем писать тесты так:
public class BasicTests1
{
BasicTester tester = new BasicTester( {constructor_args} );
@BeforeClass
public static void setUp()
{
tester.initialize();
}
@Test
public void orderedTestRun() throws Exception
{
Log.logTCTestSuiteStart( "Basic tests" );
tester.testOne();
tester.testTwo();
tester.testThree();
Log.logTCTestSuiteFinished( "Basic tests" );
}
@AfterClass
public static void tearDown()
{
tester.dispose();
}
}
public class BasicTester
{
protected {field1};
protected {field2};
protected {field3};
protected BasicTester( {class_fields} );
protected void testOne()
{
Log.logTCTestStart( "testOne" );
try
{
//test logic
}
catch( AssertionError e )
{
Log.logTCTestFailed( "testOne", e );
}
Log.logTCTestFinished( "testOne" );
}
protected void testTwo()
{
Log.logTCTestStart( "testTwo" );
try
{
//test logic
}
catch( AssertionError e )
{
Log.logTCTestFailed( "testTwo", e );
}
Log.logTCTestFinished( "testTwo" );
}
protected void testThree()
{
Log.logTCTestStart( "testThree" );
try
{
//test logic
}
catch( AssertionError e )
{
Log.logTCTestFailed( "testThree", e );
}
Log.logTCTestFinished( "testThree" );
}
}
Так как об ошибках мы сообщаем вручную, то есть смысл их перехватывать. Иначе они просто проигнорируются, и TeamCity, не дождавшись команды testFailed, будет считать тест успешным.
3. Ant task
Тут все стандартно. Единственный момент — таск 'junit' должен содержать 'showoutput=«yes»'. Это заставит выводить в стандартный out поток TestsOuput.
4. Настройки билда TeamCity
Так как TeamCity не читает сервисные команды из TestOutput junit`а, нужно вообще отключить распознавание junit тестов. Для этого необходимо открыть build configuration, перейти во вкладку 'Build parameters' и добавить такие параметры:
- system.teamcity.ant.junit-support.enabled = false
- system.teamcity.ant.testng-support.enabled = false
Вот и все. Теперь можно извращаться над тестами jUnit в TeamCity как угодно.
Автор: micherr