diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 0000000..1518fa5 --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,44 @@ +Version 1.2.2 +------------- +_22 Mar 2015_ + +* Add `getcov` command line parameters, making it easier to use XcodeCoverage in continuous integration. _Thanks to: Tom Aylesworth_ +* Add Cobertura XML generation. _Thanks to: Ellen Shapiro_ +* Support use as CocoaPod. _Thanks to: Ellen Shapiro_ +* Update to lcov 1.11. _Thanks to: Ellen Shapiro_ +* Add XcodeCoverage.xcconfig for simple project setup. + + +Version 1.1.1 +------------- +_13 Nov 2014_ + +* Exclude "Developer/SDKs" instead of "Applications/Xcode.app" so that people can use multiple versions of Xcode. _Thanks to: Cédric Luthi_ +* Quote arguments to support built products directory containing spaces. _Thanks to: Cédric Luthi_ +* Fix functionality optional post-test dialog in other locales by forcing buttons to be in English. + + +Version 1.1.0 +------------- +_30 Mar 2014_ + +* Support Xcode 5.1. _Thanks to: Mike Maietta_ +* Add optional post-test script `run_code_coverage_post.sh` to prompt whether to generate coverage report. _Thanks to: Matthew Purland_ +* Improve function coverage by specifying `--derive-func-data`. _Thanks to: jstevenco_ +* Directly include copy of lcov 1.10. + + +Version 1.0.1 +------------- +_09 Mar 2014_ + +* Fix: Use `CURRENT_ARCH` instead of `NATIVE_ARCH`. _Thanks to: Scott Densmore_ +* Improve scripts so they can be run from any working directory. +* Export `OBJROOT` so that customizations can include subprojects. + + +Version 1.0.0 +------------- +_01 Dec 2012_ + +* Initial release diff --git a/LICENSE.txt b/LICENSE.txt index ad6e42e..cd3a9f8 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,5 +1,5 @@ XcodeCoverage by Jon Reid, http://qualitycoding/about/ -Copyright 2014 Jonathan M. Reid +Copyright 2015 Jonathan M. Reid Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/README.md b/README.md index 469a851..918b6b0 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,18 @@ ![XcodeCoverage](http://qualitycoding.org/jrwp/wp-content/uploads/2014/03/XcodeCoverage.png) -These scripts provide a simple way to generate HTML reports of the code coverage of your Xcode project. +XcodeCoverage provides a simple way to generate reports of the code coverage of your Xcode project. Generated reports include HTML and Cobertura XML. - -Xcode Project Setup -=================== - -Before you get started, there are a couple of steps you will need to take to prepare your project: - -1. Depending on your version of Xcode, you may need to get Xcode's coverage instrumentation by going to Xcode > Preferences, into Downloads, and installing Command Line Tools. If you do not see this as an option in the Downloads section, the tools should already be installed. -4. In your Xcode project, enable these two build settings at the project level for your Debug configuration only: - * Instrument Program Flow - * Generate Test Coverage Files +Coverage data excludes Apple's SDKs, and the exclusion rules can be customized. Installation: Standard ====================== -1. Fork this repository; you're probably going to want to make your own modifications. +Use the standard installation if you want to customize XcodeCoverage to exclude certain files and directories, such as third-party libraries. Otherwise, the CocoaPods installation described below may be more convenient. + +1. Fork this repository. 2. Place the XcodeCoverage folder in the same folder as your Xcode project. -5. In your main target, add a Run Script build phase to execute `XcodeCoverage/exportenv.sh` +3. In your main target, add a Run Script build phase to execute `XcodeCoverage/exportenv.sh` A few people have been tripped up by the last step: Make sure you add the script to your main target (your app or library), not your test target. @@ -44,16 +37,38 @@ The steps to install via CocoaPods: Again, make sure you add the script to your main target (your app or library), not your test target. -Execution -========= +Xcode Project Setup +=================== + +XcodeCoverage comes with an xcconfig file with the build settings required to instrument your code for coverage analysis. + +If you already use an xcconfig, include it in the configuration you want to instrument: + * Standard installation: `#include "XcodeCoverage/XcodeCoverage.xcconfig"` + * CocoaPods installation: `#include "Pods/XcodeCoverage/XcodeCoverage.xcconfig"` -Immediately after installation, run your application at least once to generate the `env.sh` file, which will be placed at the same level as your `.xcodeproj` folder. This file should *not* be checked into version control, since it contains paths local to your machine. +If you don't already use an xcconfig, drag XcodeCoverage.xcconfig into your project. Where it prompts "Add to targets," deselect all targets. (Otherwise, it will be included in the bundle.) Then click on your project in Xcode's Navigator pane, and select the Info tab. For the configuration you want to instrument, select XcodeCoverage. -Once that task has been completed, the process is very simple: +If you'd rather specify the build settings by hand, enable these two settings at the project level: + * Instrument Program Flow + * Generate Test Coverage Files + +Make sure not to instrument your AppStore release. + +Execution +========= 1. Run your unit tests. 2. In Terminal, execute `getcov` in your project's XcodeCoverage folder. +`getcov` has the following command-line options: + + * `--show` or `-s`: Show HTML report. + * `--xml` or `-x`: Generate Cobertura XML. + * `-o output_dir`: Specify output directory. + * `-i info_file`: Specify name of generated lcov info file. + * `-v`: Enable verbose output. + * `-h` or `--help`: Show usage. + If you make changes to your test code without changing the production code and want a clean slate, use the `cleancov` script. If you make changes to your production code, you should clear out all build artifacts before measuring code coverage again. "Clean Build Folder" by holding down the Option key in Xcode's "Product" menu, or by using the ⌥⇧⌘K key combination. @@ -63,16 +78,14 @@ If you make changes to your production code, you should clear out all build arti * Edit Xcode scheme -> Test -> Post-actions * Set "Shell" to: `/bin/bash` * Set "Provide build settings from" to your main target - * Set script to: `source ${SRCROOT}/XcodeCoverage/run_code_coverage_post.sh` + * Set script to `source XcodeCoverage/run_code_coverage_post.sh` for standard installation. For CocoaPods installation, use `source Pods/XcodeCoverage/run_code_coverage_post.sh` Modification ============ -There are two places you may want to modify the included files if you are using the standard installation: +If you are using the standard installation, you can modify `exclude_data()` in `getcov` to specify which files to exclude, such as third-party libraries. -1. In `envcov.sh`, `LCOV_INFO` determines the name shown in the report. -2. In `getcov`, edit `exclude_data()` to specify which files to exclude, for example, third-party libraries. Credits ======= diff --git a/XcodeCoverage.podspec b/XcodeCoverage.podspec index c67035f..ecd1e28 100644 --- a/XcodeCoverage.podspec +++ b/XcodeCoverage.podspec @@ -1,16 +1,22 @@ -Pod::Spec.new do |spec| - spec.name = 'XcodeCoverage' - spec.summary = 'Code coverage for Xcode projects' - spec.version = '1.0.2' - spec.platform = :ios - spec.ios.deployment_target = '6.0' - spec.authors = {'Jon Reid' => 'jon@qualitycoding.org'} - spec.homepage = 'https://github.com/jonreid/XcodeCoverage' - spec.license = 'MIT' - spec.source = {:git => 'https://github.com/jonreid/XcodeCoverage.git', :tag => "#{spec.version}"} +Pod::Spec.new do |s| + s.name = 'XcodeCoverage' + s.version = '1.2.2' + s.summary = 'Code coverage for Xcode projects' + s.description = <<-DESC + XcodeCoverage provides a simple way to generate reports of the code coverage + of your Xcode project. Generated reports include HTML and Cobertura XML. + + Coverage data excludes Apple's SDKs, and the exclusion rules can be customized. + DESC + s.homepage = 'https://github.com/jonreid/XcodeCoverage' + s.license = 'MIT' + s.author = {'Jon Reid' => 'jon@qualitycoding.org'} + s.social_media_url = 'https://twitter.com/qcoding' + + s.ios.deployment_target = '6.0' + s.osx.deployment_target = '10.8' + s.source = {:git => 'https://github.com/jonreid/XcodeCoverage.git', :tag => 'v1.2.2'} - #these files will be brought into the filesystem, but not added to your .xcodeproj. - spec.preserve_paths = 'cleancov', 'getcov', 'llvm-cov-wrapper.sh', 'envcov.sh', 'lcov-1.11/*', 'exportenv.sh', 'run_code_coverage_post.sh' - - spec.requires_arc = true -end \ No newline at end of file + # XcodeCoverage files will be brought into the filesystem, but not added to your .xcodeproj. + s.preserve_paths = '*', '**' +end diff --git a/XcodeCoverage.xcconfig b/XcodeCoverage.xcconfig new file mode 100644 index 0000000..14722cb --- /dev/null +++ b/XcodeCoverage.xcconfig @@ -0,0 +1,5 @@ +// XcodeCoverage by Jon Reid, http://qualitycoding.org/about/ +// Source: https://github.com/jonreid/XcodeCoverage + +GCC_GENERATE_TEST_COVERAGE_FILES = YES +GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES diff --git a/cleancov b/cleancov index adcc68e..8900288 100755 --- a/cleancov +++ b/cleancov @@ -1,8 +1,8 @@ -#!/bin/sh +#!/bin/bash # XcodeCoverage by Jon Reid, http://qualitycoding/about/ -# Copyright 2014 Jonathan M. Reid. See LICENSE.txt +# Copyright 2015 Jonathan M. Reid. See LICENSE.txt -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -source ${DIR}/envcov.sh +scripts="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +source "${scripts}/envcov.sh" LCOV --zerocounters -d "${OBJ_DIR}" diff --git a/envcov.sh b/envcov.sh index fe97e91..162cd16 100644 --- a/envcov.sh +++ b/envcov.sh @@ -1,40 +1,14 @@ #!/bin/bash -# # XcodeCoverage by Jon Reid, http://qualitycoding/about/ -# Copyright 2014 Jonathan M. Reid. See LICENSE.txt +# Copyright 2015 Jonathan M. Reid. See LICENSE.txt -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -ENV_DIR="${DIR}" +scripts="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +source "${scripts}/env.sh" -if [[ "$DIR" == *Pods/XcodeCoverage* ]] -then - echo "Using Cocoapods!" - cd "${DIR}" - cd .. - cd .. - - #The env.sh file will be in the project root. - ENV_DIR="$(pwd)" -fi - -source "${ENV_DIR}/env.sh" - -# Change the report name if you like: -LCOV_INFO=Coverage.info - -XCODECOVERAGE_PATH="${SRCROOT}/XcodeCoverage" - -if [[ "$DIR" == *Pods/XcodeCoverage* ]] -then - echo "Using Cocoapods!" - #The current directory will be where XcodeCoverage is living, not in SRCROOT - XCODECOVERAGE_PATH="${DIR}" -fi - -LCOV_PATH="${XCODECOVERAGE_PATH}/lcov-1.11/bin" +LCOV_PATH="${scripts}/lcov-1.11/bin" OBJ_DIR="${OBJECT_FILE_DIR_normal}/${CURRENT_ARCH}" -# Fix for the new LLVM-COV that requires gcov to have a -v paramter +# Fix for the new LLVM-COV that requires gcov to have a -v parameter LCOV() { - "${LCOV_PATH}/lcov" "$@" --gcov-tool "${XCODECOVERAGE_PATH}/llvm-cov-wrapper.sh" + "${LCOV_PATH}/lcov" "$@" --gcov-tool "${scripts}/llvm-cov-wrapper.sh" } diff --git a/exportenv.sh b/exportenv.sh index 7dba198..30f7745 100755 --- a/exportenv.sh +++ b/exportenv.sh @@ -1,5 +1,5 @@ # XcodeCoverage by Jon Reid, http://qualitycoding/about/ -# Copyright 2014 Jonathan M. Reid. See LICENSE.txt +# Copyright 2015 Jonathan M. Reid. See LICENSE.txt -DIR="${SRCROOT}" -export | egrep '( BUILT_PRODUCTS_DIR)|(CURRENT_ARCH)|(OBJECT_FILE_DIR_normal)|(SRCROOT)|(OBJROOT)' > ${DIR}/env.sh +scripts="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +export | egrep '( BUILT_PRODUCTS_DIR)|(CURRENT_ARCH)|(OBJECT_FILE_DIR_normal)|(SRCROOT)|(OBJROOT)' > "${scripts}/env.sh" diff --git a/getcov b/getcov index 41b0ba1..8bdacf5 100755 --- a/getcov +++ b/getcov @@ -1,52 +1,142 @@ -#!/bin/sh +#!/bin/bash # XcodeCoverage by Jon Reid, http://qualitycoding/about/ -# Copyright 2014 Jonathan M. Reid. See LICENSE.txt +# Copyright 2015 Jonathan M. Reid. See LICENSE.txt -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -source "${DIR}/envcov.sh" +usage() { + echo "usage: getcov [[-s] [-x] [-o output_dir] [-i info_file] [-v]] | [-h]]" +} + +main() { + scripts="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + source "${scripts}/envcov.sh" + + LCOV_INFO=Coverage.info + output_dir="${BUILT_PRODUCTS_DIR}" + while [ "$1" != "" ]; do + case $1 in + -s|--show) + show_html=1 + echo "Show HTML Report" + ;; + -x|--xml) + generate_xml=1 + echo "Generate Cobertura XML" + ;; + -o) + shift + output_dir=$1 + echo "output_dir = ${output_dir}" + ;; + -i) + shift + LCOV_INFO=$1 + echo "LCOV_INFO = ${LCOV_INFO}" + ;; + -v) + verbose=1 + echo "Verbose" + ;; + -h|--help) + usage + echo "Show Help" + exit + ;; + *) + usage + exit 1 + esac + shift + done + + if [ "$verbose" = "1" ]; then + report_values + fi + + remove_old_report + enter_lcov_dir + gather_coverage + exclude_data + + if [ "$generate_xml" = "1" ]; then + generate_cobertura_xml + fi + + generate_html_report + + if [ "$show_html" = "1" ]; then + show_html_report + fi +} -remove_old_report() -{ - pushd "${BUILT_PRODUCTS_DIR}" - if [ -e lcov ]; then - rm -r lcov - fi - popd +report_values() { + echo "XcodeCoverage: Environment" + echo "scripts : ${scripts}" + echo "output_dir : ${output_dir}" + echo "LCOV_INFO : ${LCOV_INFO}" + echo "BUILD_DIR : ${BUILT_PRODUCTS_DIR}" + echo "SRCROOT : ${SRCROOT}" + echo "OBJ_DIR : ${OBJ_DIR}" + echo "LCOV_PATH : ${LCOV_PATH}" } -enter_lcov_dir() -{ - cd "${BUILT_PRODUCTS_DIR}" - mkdir lcov - cd lcov +remove_old_report() { + if [ "$verbose" = "1" ]; then + echo "XcodeCoverage: Removing old report" + fi + + pushd "${output_dir}" + if [ -e lcov ]; then + rm -r lcov + fi + popd } -gather_coverage() -{ - LCOV --capture --derive-func-data -b "${SRCROOT}" -d "${OBJ_DIR}" -o ${LCOV_INFO} +enter_lcov_dir() { + cd "${output_dir}" + mkdir lcov + cd lcov } -exclude_data() -{ - LCOV --remove ${LCOV_INFO} "Developer/SDKs/*" -d "${OBJ_DIR}" -o ${LCOV_INFO} - LCOV --remove ${LCOV_INFO} "main.m" -d "${OBJ_DIR}" -o ${LCOV_INFO} - # Remove other patterns here... +gather_coverage() { + if [ "$verbose" = "1" ]; then + echo "XcodeCoverage: Gathering coverage" + fi + + LCOV --capture --derive-func-data -b "${SRCROOT}" -d "${OBJ_DIR}" -o "${LCOV_INFO}" } -generate_cobertura_xml() -{ - python "${DIR}/lcov_cobertura.py" ${LCOV_INFO} --base-dir "${SRCROOT}" --output "coverage.xml" +exclude_data() { + if [ "$verbose" = "1" ]; then + echo "XcodeCoverage: Excluding data" + fi + + LCOV --remove "${LCOV_INFO}" "Developer/SDKs/*" -d "${OBJ_DIR}" -o "${LCOV_INFO}" + LCOV --remove "${LCOV_INFO}" "main.m" -d "${OBJ_DIR}" -o "${LCOV_INFO}" + # Remove other patterns here... } -generate_report() -{ - "${LCOV_PATH}/genhtml" --output-directory . ${LCOV_INFO} - open index.html +generate_cobertura_xml() { + if [ "$verbose" = "1" ]; then + echo "XcodeCoverage: Generating Cobertura XML" + fi + + python "${scripts}/lcov_cobertura.py" ${LCOV_INFO} --base-dir "${SRCROOT}" --output "coverage.xml" +} + +generate_html_report() { + if [ "$verbose" = "1" ]; then + echo "XcodeCoverage: Generating HTML report" + fi + + "${LCOV_PATH}/genhtml" --output-directory . "${LCOV_INFO}" +} + +show_html_report() { + if [ "$verbose" = "1" ]; then + echo "XcodeCoverage: Opening HTML report" + fi + + open index.html } -remove_old_report -enter_lcov_dir -gather_coverage -exclude_data -generate_cobertura_xml -generate_report +main "$@" diff --git a/lcov_cobertura.py b/lcov_cobertura.py old mode 100755 new mode 100644 diff --git a/llvm-cov-wrapper.sh b/llvm-cov-wrapper.sh index 2d64e76..e9ee147 100755 --- a/llvm-cov-wrapper.sh +++ b/llvm-cov-wrapper.sh @@ -1,10 +1,10 @@ -#!/bin/sh +#!/bin/bash # XcodeCoverage by Jon Reid, http://qualitycoding/about/ -# Copyright 2014 Jonathan M. Reid. See LICENSE.txt +# Copyright 2015 Jonathan M. Reid. See LICENSE.txt if [ "$1" = "-v" ]; then - echo "llvm-cov-wrapper 4.2.1" - exit 0 + echo "llvm-cov-wrapper 4.2.1" + exit 0 else - /usr/bin/gcov "$@" + /usr/bin/gcov "$@" fi diff --git a/run_code_coverage_post.sh b/run_code_coverage_post.sh index c809a26..a48fbbd 100644 --- a/run_code_coverage_post.sh +++ b/run_code_coverage_post.sh @@ -1,6 +1,6 @@ #!/bin/bash # XcodeCoverage by Jon Reid, http://qualitycoding/about/ -# Copyright 2014 Jonathan M. Reid. See LICENSE.txt +# Copyright 2015 Jonathan M. Reid. See LICENSE.txt button=`/usr/bin/osascript <