Skip to content

Instantly share code, notes, and snippets.

@szigetics
Forked from briancroom/code-coverage.sh
Last active December 12, 2016 08:45
Show Gist options
  • Select an option

  • Save szigetics/9ace909a7f35a2f0f3043f90894fff4c to your computer and use it in GitHub Desktop.

Select an option

Save szigetics/9ace909a7f35a2f0f3043f90894fff4c to your computer and use it in GitHub Desktop.
A pair of scripts to help with basic parsing of LLVM code-coverage output data (nowadays the generated file's name is Coverage.profdata), as produced by Xcode 8.1 . The `cov-exclusions.txt` file can be used to exclude files and globs from the output. The generated output can be used for Teamcity code coverage reporting.
A pair of scripts to help with basic parsing of LLVM code-coverage output data
(nowadays the generated file's name is Coverage.profdata), as produced by Xcode 8.1 .
The `cov-exclusions.txt` file can be used to exclude files and globs from the output.
The generated output can be used for Teamcity code coverage reporting.
The generated output is fully compatible with Teamcity :
the generated values are automatically processed by Teamcity and the results appears :
- on the build result's overview tab and
- on the build configuration's statistics tab.
ref1.: https://confluence.jetbrains.com/pages/viewpage.action?pageId=74845225#HowTo...-ImportcoverageresultsinTeamCity
ref2.: https://confluence.jetbrains.com/display/TCD10/Custom+Chart#CustomChart-predefinedStatisticsKeys
This gist is originating from briancroom's gist : https://gist.github.com/briancroom/936a54108de98a63d8cf.
Thank you really much briancroom for sharing those!
SCHEME=$1
SOURCE_ROOT=$2
XCTESTRUN_ROOT=$3
DERIVED_DATA_ROOT=$4
###
SCRIPTDIR=`dirname "$BASH_SOURCE"`
ABSOLUTE_SOURCE_ROOT=$(pushd "$SOURCE_ROOT"; pwd; popd)
PROFDATA=$(find ${DERIVED_DATA_ROOT} -name "Coverage.profdata")
echo "PROFDATA : $PROFDATA"
BINARY=$(find ${XCTESTRUN_ROOT} -path "*${SCHEME}.app/${SCHEME}")
echo "BINARY : $BINARY"
if [[ -z $PROFDATA ]]; then
echo "ERROR: Unable to find Coverage.profdata. Be sure to execute tests before running this script."
exit 1
fi
if [[ -z $BINARY ]]; then
echo "ERROR: Unable to find binary. Make sure that you have given the correct parameters!"
exit 1
fi
#get the full file list based on Coverage.profdata -> remove the unnecessary lines from the output (both from it's head and it's tail) -> call xcrun llvm-cov report on the produced full file list -> using the python script : parse the output, and output the necessary Teamcity variables
xcrun llvm-cov report -instr-profile ${PROFDATA} ${BINARY} | tail -n +3 | awk '{print $1}' | tail -r | tail -n +3 | tail -r | tr '\n' '\0' | \
xargs -0 xcrun llvm-cov report -instr-profile ${PROFDATA} ${BINARY} | "$SCRIPTDIR/parse-llvm-cov-report.py"
SCHEME=$1
SOURCE_ROOT=$2
XCODEPATH=$3 #example : /Applications/Xcode.app/Contents/Developer
BUILD_CONFIG_NAME_CAPITAL="Debug"
###
DERIVED_DATA_DIR="$SOURCE_ROOT/derivedDataDir"
XCTESTRUN_ROOT="$SOURCE_ROOT/testSymRoot"
echo "##teamcity[progressMessage 'Building Automated Tests']"
SIMULATOR_DESTINATION_UUID=$(xcrun simctl list -j | python -c "import json,sys; obj=json.load(sys.stdin); iOS_10_1_Devices = obj['devices']['iOS 10.1']; iPhone6SImulatorsWithiOS_10_1 = [item for item in iOS_10_1_Devices if item['name'] == 'iPhone 6']; print(iPhone6SImulatorsWithiOS_10_1[0]['udid']) ")
$XCODEPATH/usr/bin/xcodebuild build-for-testing -destination "platform=iOS Simulator,id=$SIMULATOR_DESTINATION_UUID" -enableCodeCoverage YES -project "$SOURCE_ROOT/$SCHEME.xcodeproj" -scheme $SCHEME -configuration "$BUILD_CONFIG_NAME_CAPITAL" -derivedDataPath "$DERIVED_DATA_DIR" SYMROOT="$XCTESTRUN_ROOT"
echo "##teamcity[progressMessage 'Running Automated Tests']"
XCTESTRUN_FILENAME=$(find $XCTESTRUN_ROOT -name "*.xctestrun")
LOG_FILE_AUTOMATED_TESTS_RUN="$SOURCE_ROOT/xcodebuildAutomatedTestsRun.log"
$XCODEPATH/usr/bin/xcodebuild test-without-building -destination "platform=iOS Simulator,id=$SIMULATOR_DESTINATION_UUID" -enableCodeCoverage YES -xctestrun $XCTESTRUN_FILENAME -derivedDataPath "$DERIVED_DATA_DIR" | tee -a "$LOG_FILE_AUTOMATED_TESTS_RUN" | xcpretty --report junit --output $SOURCE_ROOT/automated-test-results/TEST-UnitTests-$BUILD_CONFIG_NAME_CAPITAL.xml
echo "##teamcity[importData type='junit' path='$SOURCE_ROOT/automated-test-results/TEST-UnitTests-$BUILD_CONFIG_NAME_CAPITAL.xml']"
$SOURCE_ROOT/Code\ Coverage/code-coverage.sh $SCHEME $SOURCE_ROOT $XCTESTRUN_ROOT "$DERIVED_DATA_DIR"
#!/usr/bin/python
import os
import sys
import fnmatch
currentFile = None
covResults = []
inFile = open(sys.argv[1]) if len(sys.argv) > 1 else sys.stdin
currentScriptContainingFolder = os.path.abspath(os.path.dirname(sys.argv[0]))
covExclusionsFile = currentScriptContainingFolder + "/cov-exclusions.txt"
try:
fileExclusions = open(covExclusionsFile).read().splitlines()
except IOError:
fileExclusions = []
def matchesexclusion(filePath):
basename = os.path.basename(filePath)
return any([(fnmatch.fnmatch(filePath, exclusion) or fnmatch.fnmatch(basename, exclusion)) for exclusion in fileExclusions])
for line in inFile:
lineComponents = line.split("'")
if len(lineComponents) == 3 and line.startswith("File '"):
filePath = lineComponents[1]
if not matchesexclusion(filePath):
currentFile = filePath
else:
currentFile = None
print "parse-llvm-cov-report.py :: Skipping file: "+filePath
elif line.startswith("TOTAL") and currentFile != None:
lineComponents = line.split()
(fileTotalLines, fileMissedLines) = (float(lineComponents[4]), float(lineComponents[5]))
covPercentage = (fileTotalLines-fileMissedLines) / fileTotalLines
covResults.append((currentFile, covPercentage, fileTotalLines, fileMissedLines))
covResults.sort(key=lambda x: x[1], reverse=True)
# for (file, coverage, totalLines, missedLines) in covResults:
# print file + ": {0:.2%}".format(coverage)
totalLines = sum([x[2] for x in covResults])
missedLines = sum([x[3] for x in covResults])
covAverage = (totalLines-missedLines) / totalLines if totalLines>0 else 0
print "parse-llvm-cov-report.py :: fileExclusions : "
print fileExclusions
print "##teamcity[buildStatisticValue key='CodeCoverageAbsLTotal' value='%i']" % totalLines
print "##teamcity[buildStatisticValue key='CodeCoverageAbsLCovered' value='%d']" % (totalLines-missedLines)
print "parse-llvm-cov-report.py :: Coverage average is: {0:.2%}".format(covAverage)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment