Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: Single vs Multiple coverage.xml files #34

Open
kenjones-cisco opened this issue Sep 28, 2017 · 9 comments
Open

Question: Single vs Multiple coverage.xml files #34

kenjones-cisco opened this issue Sep 28, 2017 · 9 comments
Labels

Comments

@kenjones-cisco
Copy link

Description

In the README I noticed the following section:

You must end-up with one coverage file per directory:

pkg1/coverage.xml
pkg2/coverage.xml
pkg3/coverage.xml
...

Currently I'm able to generate a single coverage.xml file for an entire project with multiple packages within the same project. And cobertura within Jenkins is able to read and process the file and show all of the packages.

Example single coverage.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE coverage SYSTEM "http://cobertura.sourceforge.net/xml/coverage-03.dtd">
<coverage line-rate="0" branch-rate="0" version="" timestamp="1506622955562">
	<sources>
		<source>/usr/local/go/src</source>
		<source>/go/src</source>
		<source>/authlib/src</source>
	</sources>
	<packages>
		<package name="gitscm.cisco.com/ccdev/authlib/authz" line-rate="0" branch-rate="0" complexity="0">
			<classes>
				<class name="-" filename="gitscm.cisco.com/ccdev/authlib/authz/context.go" line-rate="0" branch-rate="0" complexity="0">
					<methods>
						<method name="key" signature="" line-rate="0" branch-rate="0">
							<lines>
								<line number="11" hits="11"></line>
							</lines>
						</method>
						<method name="GetUsername" signature="" line-rate="0" branch-rate="0">
							<lines>
								<line number="16" hits="6"></line>
								<line number="17" hits="5"></line>
								<line number="19" hits="1"></line>
							</lines>
						</method>
						<method name="SetUsername" signature="" line-rate="0" branch-rate="0">
							<lines>
								<line number="24" hits="5"></line>
							</lines>
						</method>
					</methods>
					<lines>
						<line number="11" hits="11"></line>
						<line number="16" hits="6"></line>
						<line number="17" hits="5"></line>
						<line number="19" hits="1"></line>
						<line number="24" hits="5"></line>
					</lines>
				</class>
			</classes>
		</package>
		<package name="gitscm.cisco.com/ccdev/authlib/authz/casbin" line-rate="0" branch-rate="0" complexity="0">
			<classes>
				<class name="-" filename="gitscm.cisco.com/ccdev/authlib/authz/casbin/ldap_role_manager.go" line-rate="0" branch-rate="0" complexity="0">
					<methods>
						<method name="CheckLdapEnv" signature="" line-rate="0" branch-rate="0">
							<lines>
								<line number="32" hits="4"></line>
								<line number="33" hits="1"></line>
								<line number="35" hits="3"></line>
								<line number="36" hits="1"></line>
								<line number="38" hits="2"></line>
								<line number="39" hits="1"></line>
								<line number="41" hits="1"></line>
							</lines>
						</method>
						<method name="LDAPRoleManager" signature="" line-rate="0" branch-rate="0">
							<lines>
								<line number="46" hits="1"></line>
							</lines>
						</method>
						<method name="@46:9" signature="" line-rate="0" branch-rate="0">
							<lines>
								<line number="47" hits="1"></line>
								<line number="48" hits="1"></line>
								<line number="49" hits="1"></line>
								<line number="50" hits="1"></line>
								<line number="53" hits="1"></line>
								<line number="54" hits="1"></line>
								<line number="56" hits="1"></line>
							</lines>
						</method>
						<method name="NewLdapRoleManager" signature="" line-rate="0" branch-rate="0">
							<lines>
								<line number="62" hits="2"></line>
								<line number="70" hits="2"></line>
								<line number="71" hits="2"></line>
								<line number="72" hits="1"></line>
								<line number="74" hits="1"></line>
								<line number="78" hits="1"></line>
							</lines>
						</method>
					</methods>
					<lines>
						<line number="32" hits="4"></line>
						<line number="33" hits="1"></line>
						<line number="35" hits="3"></line>
						<line number="36" hits="1"></line>
						<line number="38" hits="2"></line>
						<line number="39" hits="1"></line>
						<line number="41" hits="1"></line>
						<line number="46" hits="1"></line>
						<line number="47" hits="1"></line>
						<line number="48" hits="1"></line>
						<line number="49" hits="1"></line>
						<line number="50" hits="1"></line>
						<line number="53" hits="1"></line>
						<line number="54" hits="1"></line>
						<line number="56" hits="1"></line>
						<line number="62" hits="2"></line>
						<line number="70" hits="2"></line>
						<line number="71" hits="2"></line>
						<line number="72" hits="1"></line>
						<line number="74" hits="1"></line>
						<line number="78" hits="1"></line>
					</lines>
				</class>
			</classes>
		</package>
	</packages>
</coverage>
  1. Is there a technical limitation within SonarQube that requires the coverage to be done as one coverage.xml per package? Or is this rule imposed by the plugin?

  2. As a follow up, does the coverage.xml have to be in the same directory as the code? Or is it possible to leverage a cover directory that has a directory for each package and the coverage.xml file exists within that directory?

Example Directory structure for coverage:

cover/
    github.com/org/repo/pkg1/coverage.xml
    github.com/org/repo/pkg2/coverage.xml
    github.com/org/repo/pkg3/coverage.xml
    ...
@thibaultfalque
Copy link
Collaborator

Hi,

Thanks for your questions.

  1. The plugin use the report generated by gocov-xml. We used gocov to convert a coverage profile generate by go test.
    But we can't launch go test for all packages in one time (if you have a any idea or solution for do that,...). So we need to launch go test and generate the coverage profile and send this profile to gocov for convert and the conversion to gocov-xml.

  2. It's not a problem. I used Files.walk for explore the project and visit directories.

How did you do for generate a single coverage file ? If it's possible I will can modify the plugin to use a single coverage file.

@kenjones-cisco
Copy link
Author

Generating single coverage.xml

workdir=cover
profile="$workdir/cover.out"
mode=count

for pkg in $(glide nv);
do
    for subpkg in $(go list "${pkg}");
    do
        f="$workdir/$(echo "$subpkg" | tr / -).cover"
        go test -v -covermode="$mode" -coverprofile="$f" "$subpkg" >> test.out
    done
done

set -- "$workdir"/*.cover
if [ ! -f "$1" ]; then
    echo "No Test Cases"; exit 0
fi
echo "mode: $mode" >"$profile"
grep -h -v "^mode:" "$workdir"/*.cover >>"$profile"

rm -f test.xml coverage.xml

go2xunit -input test.out -output test.xml

gocov convert "$profile" | gocov-xml > coverage.xml

That is how I have it scripted to generate the test.xml and coverage.xml that I have been using.

My alternate approach would be just to write the coverage.xml files into the cover/ directory as I don't like the idea of writing any files to my actual package directories.

@danielleberre
Copy link
Contributor

@thibaultfalque I guess that making sure to search first a single cover file in the root directory else look for multiple cover files in subdirectories could do the trick.

@kenjones-cisco thanks for the script. Would you agree that we display it in the README page of the script?

@kenjones-cisco
Copy link
Author

Sure, no problem.

@kenjones-cisco
Copy link
Author

kenjones-cisco commented Sep 29, 2017

FYI, to make it not specific to glide, you should can use this:

workdir=cover
profile="$workdir/cover.out"
mode=count

for pkg in $(go list ./...);
do
    f="$workdir/$(echo "$pkg" | tr / -).cover"
    go test -v -covermode="$mode" -coverprofile="$f" "$pkg" >> test.out
done

set -- "$workdir"/*.cover
if [ ! -f "$1" ]; then
    rm -f "$results" || :
    echo "No Test Cases"; exit 0
fi
echo "mode: $mode" >"$profile"
grep -h -v "^mode:" "$workdir"/*.cover >>"$profile"

rm -f test.xml coverage.xml

go2xunit -input test.out -output test.xml

gocov convert "$profile" | gocov-xml > coverage.xml

@danielleberre
Copy link
Contributor

@thibaultfalque are we done here?

@thibaultfalque
Copy link
Collaborator

See the PR by @kernle32dll #50

@kernle32dll
Copy link
Contributor

For a bit more context what gocov test ./... does - it internally does exactly that. Its walks trough the folders, and executes go test, and gocov convert. The nice thing is, that this method aggregates the results, and creates a single coverage.xml, without some shell magic (which is good, since this way it can be used across platforms).

Also also - Golang 1.10 will bring support for go test ./... -coverprofile..., which was not possible so far (hence all the extra hops with executing go test in each package separately).

@thibaultfalque
Copy link
Collaborator

Thanks @kernle32dll for your explanation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants