Publishing nosetests results in Jenkins CI

While trying to publish test results in Jenkins CI via the xUnit plugin, I’ve set up the Post-build Actions section in Jenkins according to what the nosetests documentation suggests, that is, to “tick the box named “Publish JUnit test result report”” and referenced the correct file.

However, I was repeatedly stumbling upon an error:

WARNING: The file '/var/lib/jenkins/workspace/Project/nosetests.xml' is an invalid file.
WARNING: At line 1 of file:/var/lib/jenkins/workspace/Project/nosetests.xml:cvc-complex-type.3.2.2: Attribute 'skip' is not allowed to appear in element 'testsuite'.
ERROR: The result file '/var/lib/jenkins/workspace/Project/nosetests.xml' for the metric 'JUnit' is not valid. The result file has been skipped.

Turns out, my nosetests.xml file does indeed contain the skip attribute. And that's also in line with the example in the official documentation.
Much to my surprise, though, running a few web searches made me realize there aren't many other users of Jenkins + xUnit plugin + nosetests who have the same problem.

To fix this, it looked like I had to write my one XLS file. All you need to do is create two templates, one matching the "skip" attribute, and the other matching everything else.

The "skip"-matching template will simply get rid of the attribute altogether. The other will pass everything else as it is.

By taking cue from this StackOverflow answer, the result is as follows:

<xsl:stylesheet version="1.0" xmlns:xsl="">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" omit-xml-declaration="no" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="@skip" />
    <xsl:template match="@*|node()">
            <xsl:apply-templates select="@*|node()"/>


Save it as nosetests.xsl. Now, armed with your shiny XSL file, put it in the $JENKINS_HOME/userContent directory, say in userContent/xunit_xsl/nosetests.xsl.

In the job config page, under the Post-Build Actions section, change the type from JUnit to Custom, and provide a reference to the XSD file you've created, in the form of $JENKINS_HOME/userContent/xunit_xsl/nosetests.xsl.

Save, run, and happily enjoy your test results!


Timezones and DST in Python

It’s incredible how fiddly it is to work with timezones.

Today, 14th of June—and this is important—I was trying to convert a made-up datetime from “Europe/London” to UTC.

I instinctively tried out this:
>>> almostMidnight =, minute=59, second=59, microsecond=999999, tzinfo=pytz.timezone('Europe/London'))
>>> almostMidnight
datetime.datetime(2017, 6, 14, 23, 59, 59, 999999, tzinfo=<DstTzInfo 'Europe/London' GMT0:00:00 STD>)

At this point you will notice it didn’t take into account the DST offset (it should read BST).

As a further confirmation, converting to UTC keeps the same time:
>>> pytz.UTC.normalize(almostMidnight)
datetime.datetime(2017, 6, 14, 23, 59, 59, 999999, tzinfo=<UTC>)

Notice this result would be fine during the winter, so depending how much attention you devote and when you write the code you might miss out on this bug – which is why I love having the same suite of tests always running on a system that lives right after the upcoming DST change.

Even more subtler, if you were to try and convert to a different timezone, a geographical timezone that observes DST, you would see this:
>>> almostMidnight.astimezone(pytz.timezone('Europe/Rome'))
datetime.datetime(2017, 6, 15, 1, 59, 59, 999999, tzinfo=<DstTzInfo 'Europe/Rome' CEST+2:00:00 DST>)

Interesting. Now DST is accounted for. So converting to geographical timezones might also mask the problem.

Long story short, the correct way *I believe* to convert the timezone of a datetime object to UTC is to create a naive datetime object (no timezone info attached) representing localtime, and then call the “localize” of the timezone of interest. In code:
>>> almostMidnight =, minute=59, second=59, microsecond=999999)
>>> almostMidnight
datetime.datetime(2017, 6, 14, 23, 59, 59, 999999)
>>> pytz.timezone('Europe/London').localize(almostMidnight).astimezone(pytz.UTC)
datetime.datetime(2017, 6, 14, 22, 59, 59, 999999, tzinfo=<UTC>)

There’s a very nice read on timezones by Armin Ronacher, which I recommend.

Nosetests and the docstrings

For some reason when you use the -v switch in nosetests, instead of using the test name, the runner uses the docstring (and only first line, for that matter).

Solution: install the “nose-ignore-docstring” plugin:
sudo easy_install nose-ignore-docstring
and then enable it by adding:

to ~/.noserc

For additional information, I’ll point you to the plugin web page on PyPy.

PowerShell and vSphere

In the last post I showed very quickly how you can use PowerShell to connect to a vSphere server and change the NIC for a VM.

Today I was faced with another problem. As I discovered, much to my horror, that the %windir%\winsxs folder was taking up a good amount of the space on the HD and that you should not delete anything in there and that resistance is futile but the occupied disk can be (a little) reduced.

The only alternative was to increase the size of the HD. When trying to do it manually, I got this error:

Error on eor-bts-prebv:Permission to perform this operation was denied.
You do not hold privilege “Virtual machine > Configuration > Change resource” on virtual machine “myVM”
Error Stack
Call “VirtualMachine.Reconfigure” for object “myVM” on vCenter Server “vCenter” failed.

So I gave a go to PowerShell. After connecting (see the previous post), I:

  1. Got hold of my VM: $myvm = Get-VM -Name "myVM"
  2. Looked at the HDs, and retrieved ID and capacity: Get-HardDisk -VM $myvm | % {$_.Id, $_.CapacityGB}
  3. Grabbed the HD of interest: $hd = Get-HardDisk -vm $myvm -Id "VirtualMachine-vm-2767/2000"
  4. Set the capacity to 20 GB: Set-HardDisk -HardDisk $hd -CapacityGB 20

Needless to say, it worked like a charm.

PowerShell and vSphere

There is a PowerShell snap-in (a mechanism to add new cmdlets, I’ll try and write something more about modules, snap-ins etc in the future) which is quite useful – and sometimes vital – to manage virtual machines in vSphere. To add it to the shell you just need to issue Add-PSSnapin VMware.VimAutomation.Core

If all goes well you can now connect to the vCenter server, that is: Connect-VIServer $VcenterHostname

At this point is quite easy to get the list of all VMs currently present on the server: Get-VM (told you it was easy :). If you specify a machine name, then obviously you’ll get that VM.

With the VM, you will be able to perform tasks, such as changing the network adapter – which, incidentally, you cannot do via the vSphere client. For instance, to change the adapter from E1000 to Vmxnet3, just type:  Get-VM myVM | Get-NetworkAdapter | Set-NetworkAdapter -Type "vmxnet3"

A popup will appear, asking if you want to continue. Notice that the previous command assumes you only have one NIC. If two or more NICs are present on the VM you’ll have to specify a properly crafted Where-Object clause after Get-NetworkAdapter (Get-Member is your friend!)