Use InSpec XML resource with XPath to test attribute values

Challenge

Find an XML nodes with an attribute key called name and whose value equals url. For the found node test if a different attribute’s actual value matches the expected value.

Test Data

database.xml (Store as /tmp/database.xml for test purposes)

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd" default-lazy-init="true">
<bean id="dataSource" class="com.myapplication.base.persistency.support.DecoratedDataSource" parent="oracleBaseDataSource" scope="singleton" lazy-init="true">
	<property name="type" ref="ORACLE_11" />
	<property name="name" value="MYAPPLICATION" />
	<property name="url" value="jdbc:oracle:thin:@databaseserver.domain.tld:1521/DBO.DOMAIN.TLD" />
	<property name="username" value="MYUSERNAME" />
	<property name="password">
	<bean class="com.mycorp.core.util.crypt.PasswordHelper" factory-method="decrypt">
	<constructor-arg value="" />
</bean>
</property>
</bean>
</beans>

Solution

I tested after attribute support was merged into InSpec with PR #2423 and got an error because I was still comparing the result with a string literal rather than an array:

  File /tmp/database.xml
     ✔  should exist
  XML /tmp/database.xml
     ∅  ["//property[@name='url']/@value"] should eq "jdbc:oracle:thin:@databaseserver.domain.tld:1521/DBO.DOMAIN.TLD"

     expected: "jdbc:oracle:thin:@databaseserver.domain.tld:1521/DBO.DOMAIN.TLD"
          got: ["jdbc:oracle:thin:@databaseserver.domain.tld:1521/DBO.DOMAIN.TLD"]

     (compared using ==)


Test Summary: 1 successful, 1 failure, 0 skipped

But since the eval is returning an array I simply switched to cmp and it works:

  File /tmp/database.xml
     ✔  should exist
  XML /tmp/database.xml
     ✔  ["//property[@name='url']/@value"] should cmp == "jdbc:oracle:thin:@databaseserver.domain.tld:1521/DBO.DOMAIN.TLD"

Test Summary: 2 successful, 0 failures, 0 skipped

The test itself looks like this:

testfile   = '/tmp/database.xml'
datasource = 'jdbc:oracle:thin:@databaseserver.domain.tld:1521/DBO.DOMAIN.TLD'

if file(testfile).exist?
  describe xml(testfile) do
    its(['//property[@name="url"]/@value']) { should eq datasource }
  end
end

The @value in the test means: return the value of the node’s attribute called value. Replace it with whatever attribute’s value you want to query.

The Docs have been updated to showcase the syntax: https://www.inspec.io/docs/reference/resources/xml/