WSDL Explained: The Contract Behind Every SOAP API
WSDL is the WSDL — Web Services Description Language. It's the source of truth for every SOAP API. Here's how to read it.
What WSDL is
WSDL (Web Services Description Language) is an XML document that describes everything about a SOAP service: what operations it offers, what inputs they take, what outputs they return, what faults they can raise, and where to send requests.
If OpenAPI is the contract for REST, WSDL is the contract for SOAP. Except WSDL is older, denser, and non-optional: you cannot build a production SOAP client without it. For REST you can eyeball an endpoint and wing it. For SOAP you read the WSDL.
The five sections of a WSDL
Every WSDL has five building blocks:
1. <types> — the data shapes
XML Schema (XSD) definitions for every input and output type:
<types>
<xsd:schema targetNamespace="http://demo.totalshiftleft.ai/users">
<xsd:element name="GetUser">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Id" type="xsd:int"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="GetUserResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="User" type="tns:User"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</types>
Every field has an explicit type. No guessing.
2. <message> — request and response pairings
Groups types into messages that travel together:
<message name="GetUserRequest">
<part name="parameters" element="tns:GetUser"/>
</message>
<message name="GetUserResponse">
<part name="parameters" element="tns:GetUserResponse"/>
</message>
3. <portType> — the operations
The abstract interface: "this service has operations X, Y, Z":
<portType name="UserServicePortType">
<operation name="GetUser">
<input message="tns:GetUserRequest"/>
<output message="tns:GetUserResponse"/>
<fault name="UserNotFound" message="tns:UserNotFoundFault"/>
</operation>
</portType>
Read this like a class interface in Java or C#.
4. <binding> — how operations travel
The concrete protocol details: "these operations go over SOAP 1.1 over HTTP, and here's how":
<binding name="UserServiceBinding" type="tns:UserServicePortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GetUser">
<soap:operation soapAction="http://demo.totalshiftleft.ai/users/GetUser"/>
<input><soap:body use="literal"/></input>
<output><soap:body use="literal"/></output>
</operation>
</binding>
The soapAction is the HTTP header you must send with the request.
5. <service> — the address
Where to actually POST the request:
<service name="UserService">
<port name="UserServicePort" binding="tns:UserServiceBinding">
<location xmlns="http://schemas.xmlsoap.org/wsdl/soap/" url="https://demo.totalshiftleft.ai/soap"/>
</port>
</service>
How to read a WSDL quickly
When handed a WSDL, go bottom-up:
<service>→ get the URL.<binding>→ check the SOAPAction for the operation you care about.<portType>→ find the operation name, its input, output, and possible faults.<message>→ look up the element the operation refers to.<types>→ find that element's schema and understand field-by-field what's required.
Doing this for every operation you plan to test takes 5–10 minutes per operation at first, 30 seconds once you're fluent.
WSDL-driven testing
The whole point of WSDL is that you shouldn't hand-write anything. Tools that consume WSDL:
- SOAPUI / ReadyAPI — generate a full test project from a WSDL URL
- .NET
svcutil.exe— generates a typed C# client - Java
wsimport— generates JAX-WS client stubs - Python
zeep— runtime WSDL parsing with a Pythonic client - ShiftLeft — generates full negative and positive test suites from WSDL, with validation against the XSD baked in
A good WSDL-driven test suite covers:
- Every operation — at least one happy-path call.
- Every fault — trigger each declared fault and assert its structure matches.
- Boundary values for every XSD constraint — min/max length, pattern, enumeration.
- Required vs optional fields — omit required, assert fault; include optional, assert accepted.
- Namespace correctness — swap a namespace prefix, assert 500 or specific fault.
Common WSDL gotchas
1. RPC style vs document style. Older WSDLs use style="rpc", newer ones use style="document". They serialize differently. If your tooling mis-detects, your envelopes won't match what the server expects.
2. Imports. Large WSDLs <import> other WSDLs or XSDs. If you download one without its imports, tools fail cryptically. Use wget --recursive or your tool's "download with imports" option.
3. Mismatched endpoints. The <service><port> URL in the WSDL might point to dev or staging by accident. Always verify the URL matches the environment you're testing.
4. Optional <wsdl:documentation>. Most WSDLs skip human-readable descriptions. If you have them, read them — they often document business rules the schema can't express.
5. Dynamic WSDLs. Some servers generate the WSDL at request time based on server state. Version-check the WSDL as part of your test run so schema drift is caught early.
What's next
Next: the SOAP testing guide — practical patterns for testing SOAP services, including fault handling, XPath assertions, and contract validation.
Related lessons
SOAP isn't dead — it runs banks, insurance, and government. Here's how it actually works.
SOAP testing is different. XPath, XSDs, SOAP Faults. Here's how to do it without losing your weekends.
The same operation in three protocols. Pick the right one for the job — and test it right.