Give support to JUnit output format for sogo-tests

To integrate with CI system.

sogo-tests now accepts a flag (-f) to determine the output format:

  * text : Current behaviour and default value
  * junit: XML output suitable for CI system such as Jenkins
This commit is contained in:
Enrique J. Hernández Blasco 2015-12-17 11:56:02 +01:00
parent 2ad00f8cef
commit 0c5f4edb36
4 changed files with 191 additions and 12 deletions

View file

@ -154,7 +154,8 @@ static NSString *SOGoTestAssertException = @"SOGoTestAssertException";
}
NS_ENDHANDLER;
[testRunner incrementTestCounter: failureCode];
[testRunner incrementTestCounter: failureCode
afterMethod: NSStringFromSelector (testMethod)];
}
- (BOOL) run

View file

@ -35,20 +35,31 @@ typedef enum {
SOGoTestFailureError = 2,
} SOGoTestFailureCode;
typedef enum {
SOGoTestTextOutputFormat = 0,
SOGoTestJUnitOutputFormat
} SOGoTestOutputFormat;
@interface SOGoTestRunner : NSObject
{
NSMutableArray *messages;
/* An array of arrays whose components are the method name and the
failure message if any */
NSMutableArray *performedTests;
int testCount;
int failuresCount;
int errorsCount;
BOOL hasFailed;
SOGoTestOutputFormat reportFormat;
}
+ (SOGoTestRunner *) testRunner;
+ (SOGoTestRunner *) testRunnerWithFormat: (SOGoTestOutputFormat) reportFormat;
- (void) setReportFormat: (SOGoTestOutputFormat) format;
- (int) run;
- (void) incrementTestCounter: (SOGoTestFailureCode) failureCode;
- (void) incrementTestCounter: (SOGoTestFailureCode) failureCode
afterMethod: (NSString *) methodName;
- (void) reportException: (NSException *) exception
method: (NSString *) methodName
withCode: (SOGoTestFailureCode) failureCode;

View file

@ -22,6 +22,7 @@
#import <Foundation/NSArray.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSDate.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSException.h>
@ -35,11 +36,12 @@
@implementation SOGoTestRunner
+ (SOGoTestRunner *) testRunner
+ (SOGoTestRunner *) testRunnerWithFormat: (SOGoTestOutputFormat) reportFormat
{
SOGoTestRunner *testRunner;
testRunner = [self new];
[testRunner setReportFormat: reportFormat];
[testRunner autorelease];
return testRunner;
@ -53,7 +55,8 @@
failuresCount = 0;
errorsCount = 0;
hasFailed = NO;
messages = [NSMutableArray new];
performedTests = [NSMutableArray new];
reportFormat = SOGoTestTextOutputFormat;
}
return self;
@ -61,10 +64,15 @@
- (void) dealloc
{
[messages release];
[performedTests release];
[super dealloc];
}
- (void) setReportFormat: (SOGoTestOutputFormat) format
{
reportFormat = format;
}
- (int) run
{
NSEnumerator *allTestClasses;
@ -95,11 +103,16 @@
}
- (void) incrementTestCounter: (SOGoTestFailureCode) failureCode
afterMethod: (NSString *) methodName
{
static char failureChars[] = { '.', 'F', 'E' };
testCount++;
fprintf (stderr, "%c", failureChars[failureCode]);
if (reportFormat == SOGoTestTextOutputFormat)
fprintf (stderr, "%c", failureChars[failureCode]);
if (failureCode == SOGoTestFailureSuccess)
[performedTests addObject: [NSArray arrayWithObjects: methodName, @"", nil]];
/* else has been added by reportException method */
}
- (void) reportException: (NSException *) exception
@ -134,13 +147,27 @@
errorsCount++;
}
[message appendString: @"\n"];
[messages addObject: message];
[performedTests addObject:
[NSArray arrayWithObjects: methodName, message, [NSNumber numberWithInt: failureCode], nil]];
}
- (void) displayReport
- (void) displayTextReport
{
static NSString *separator = @"\n======================================================================\n";
NSArray *performedTest;
NSMutableArray *messages;
NSString *reportMessage;
NSUInteger i, max;
messages = [NSMutableArray new];
max = [performedTests count];
for (i = 0; i < max; i++)
{
performedTest = [performedTests objectAtIndex: i];
if ([[performedTest objectAtIndex: 1] length] > 0)
[messages addObject: [performedTest objectAtIndex: 1]];
}
if ([messages count])
{
@ -148,6 +175,9 @@
reportMessage = [messages componentsJoinedByString: separator];
fprintf (stderr, "%s", [reportMessage UTF8String]);
}
[messages release];
fprintf (stderr,
"\n----------------------------------------------------------------------\n"
"Ran %d tests\n\n", testCount);
@ -158,4 +188,58 @@
fprintf (stderr, "OK\n");
}
- (void) displayJUnitReport
{
/* Follow JUnit.xsd defined by Apache-Ant project */
NSArray *performedTest;
NSMutableString *reportMessage;
NSUInteger i, max;
/* Header */
reportMessage = [NSMutableString stringWithFormat: @"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
@"<testsuite "
@"name=\"%@\" id=\"0\" tests=\"%d\" errors=\"%d\" failures=\"%d\" "
@"timestamp=\"%@\">\n"
@"<desc>%@</desc>\n",
@"SOGoUnitTests", testCount, errorsCount, failuresCount,
[NSDate date],
@"SOGo and SOPE Unit tests"];
/* Test cases */
max = [performedTests count];
for (i = 0; i < max; i++)
{
performedTest = [performedTests objectAtIndex: i];
[reportMessage appendFormat: @"<testcase name=\"%@\">\n", [performedTest objectAtIndex: 0]];
if ([[performedTest objectAtIndex: 1] length] > 0)
{
if ([performedTest count] > 2 && [[performedTest objectAtIndex: 2] intValue] == SOGoTestFailureFailure)
[reportMessage appendFormat: @"<failure>%@</failure>\n", [performedTest objectAtIndex: 1]];
else
[reportMessage appendFormat: @"<error>%@</error>\n", [performedTest objectAtIndex: 1]];
}
[reportMessage appendString: @"</testcase>\n"];
}
/* End */
[reportMessage appendString: @"</testsuite>"];
fprintf (stdout, "%s", [reportMessage UTF8String]);
}
- (void) displayReport
{
switch (reportFormat)
{
case SOGoTestTextOutputFormat:
[self displayTextReport];
break;
;;
case SOGoTestJUnitOutputFormat:
[self displayJUnitReport];
break;
;;
}
}
@end

View file

@ -21,15 +21,91 @@
*/
#import <Foundation/Foundation.h>
#import <Foundation/NSProcessInfo.h>
#import "SOGoTestRunner.h"
int main()
static void Usage ()
{
/* Print usage and exit */
NSLog (@"sogo-tests [-h|--help] [-f|--format=text|junit]\n"
@" -h, --help\t\t\tdisplay this help information\n"
@" -f, --format=text|junit\treport format. Default: text\n\n");
exit(0);
}
static SOGoTestOutputFormat ParseArguments (NSArray *args)
{
/* Parse arguments from command line */
BOOL help = NO;
NSString *arg, *format = nil;
NSUInteger i, max;
SOGoTestOutputFormat outFormat;
max = [args count];
/* Skip program name */
i = 1;
while (!help && i < max)
{
arg = [args objectAtIndex: i];
if ([arg isEqualToString: @"-f"] || [arg isEqualToString: @"--format"])
{
NSArray *validFormats = [NSArray arrayWithObjects: @"text", @"junit", nil];
i++;
if (i < max)
{
arg = [args objectAtIndex: i];
if ([validFormats containsObject: arg])
format = arg;
else
{
help = YES;
NSLog (@"Invalid format: '%@'. Use 'text' or 'junit'", arg);
}
}
else
{
NSLog (@"Missing format argument");
help = YES;
}
}
else if ([arg isEqualToString: @"-h"]
|| [arg isEqualToString: @"--help"])
help = YES;
else
{
NSLog (@"Invalid command line argument: '%@'", arg);
help = YES;
}
i++;
}
if (help)
{
Usage ();
}
if (format)
{
if ([format isEqualToString: @"text"])
outFormat = SOGoTestTextOutputFormat;
else if ([format isEqualToString: @"junit"])
outFormat = SOGoTestJUnitOutputFormat;
}
else
outFormat = SOGoTestTextOutputFormat;
return outFormat;
}
int main(int argc, char *argv[], char *env[])
{
NSAutoreleasePool *pool;
int rc;
NSDictionary *defaults;
NSUserDefaults *ud;
SOGoTestOutputFormat reportFormat;
pool = [NSAutoreleasePool new];
@ -42,7 +118,14 @@ int main()
forName: @"sogo-tests-volatile"];
[ud addSuiteNamed: @"sogo-tests-volatile"];
rc = [[SOGoTestRunner testRunner] run];
/* Process arguments */
[NSProcessInfo initializeWithArguments: argv
count: argc
environment: env];
reportFormat = ParseArguments ([[NSProcessInfo processInfo] arguments]);
rc = [[SOGoTestRunner testRunnerWithFormat: reportFormat] run];
[pool release];
return rc;