Skip to content

Commit 4a6723a

Browse files
Merge pull request #314 from fdelpoggio/webSocket-support
Add WebSocket support to JMeterDSL
2 parents 325c554 + 65f538a commit 4a6723a

File tree

20 files changed

+1425
-5
lines changed

20 files changed

+1425
-5
lines changed
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
# WebSocket Sampler Documentation
2+
3+
## Overview
4+
5+
The `DslWebsocketSampler` class provides a Java DSL for creating WebSocket performance tests using JMeter. It supports the full WebSocket lifecycle including connection, data transmission, and disconnection operations.
6+
7+
## Features
8+
9+
- **Connection Management**: Establish and close WebSocket connections
10+
- **Data Transmission**: Send and receive WebSocket messages
11+
- **URL Parsing**: Automatic parsing of WebSocket URLs (ws:// and wss://)
12+
- **Timeout Configuration**: Configurable connection and response timeouts
13+
- **TLS Support**: Secure WebSocket connections with WSS protocol
14+
- **Fluent API**: Method chaining for easy configuration
15+
16+
## Main Components
17+
18+
### 1. DslWebsocketSampler (Main Class)
19+
20+
The main class that provides static factory methods for creating different types of WebSocket samplers.
21+
22+
#### Static Methods
23+
24+
- `webSocketSampler()` - Creates a basic WebSocket sampler
25+
- `connect()` - Creates a WebSocket connection sampler
26+
- `connect(String url)` - Creates a WebSocket connection sampler with URL parsing
27+
- `disconnect()` - Creates a WebSocket disconnection sampler
28+
- `write()` - Creates a WebSocket write sampler
29+
- `read()` - Creates a WebSocket read sampler
30+
31+
### 2. DslConnectSampler (Connection Operations)
32+
33+
Handles WebSocket connection establishment.
34+
35+
#### Configuration Methods
36+
37+
- `connectionTimeout(String timeout)` - Sets connection timeout in milliseconds
38+
- `responseTimeout(String timeout)` - Sets response timeout in milliseconds
39+
- `server(String server)` - Sets the WebSocket server hostname
40+
- `port(String port)` - Sets the WebSocket server port
41+
- `path(String path)` - Sets the WebSocket path
42+
- `tls(boolean tls)` - Enables/disables TLS encryption
43+
44+
#### URL Parsing
45+
46+
The `connect(String url)` method automatically parses WebSocket URLs and extracts:
47+
- Protocol (ws:// or wss://)
48+
- Hostname
49+
- Port (defaults to 80 for ws://, 443 for wss://)
50+
- Path and query parameters
51+
- TLS configuration
52+
53+
**Supported URL formats:**
54+
- `ws://localhost:8080/websocket`
55+
- `wss://example.com:8443/chat?room=general`
56+
- `wss://api.example.com/ws`
57+
58+
### 3. DslDisconnectSampler (Disconnection Operations)
59+
60+
Handles WebSocket connection closure.
61+
62+
#### Configuration Methods
63+
64+
- `responseTimeout(String timeout)` - Sets response timeout in milliseconds
65+
- `statusCode(String statusCode)` - Sets the close status code (e.g., "1000" for normal closure)
66+
67+
### 4. DslWriteSampler (Write Operations)
68+
69+
Handles sending data through WebSocket connections.
70+
71+
#### Configuration Methods
72+
73+
- `connectionTimeout(String timeout)` - Sets connection timeout in milliseconds
74+
- `requestData(String requestData)` - Sets the data to send
75+
- `createNewConnection(boolean createNewConnection)` - Whether to create a new connection
76+
- `loadDataFromFile(boolean loadDataFromFile)` - Whether to load data from a file
77+
78+
### 5. DslReadSampler (Read Operations)
79+
80+
Handles receiving data from WebSocket connections.
81+
82+
#### Configuration Methods
83+
84+
- `connectionTimeout(String timeout)` - Sets connection timeout in milliseconds
85+
- `responseTimeout(String timeout)` - Sets response timeout in milliseconds
86+
- `createNewConnection(boolean createNewConnection)` - Whether to create a new connection
87+
88+
## Usage Examples
89+
90+
### Basic WebSocket Test
91+
92+
```java
93+
import static us.abstracta.jmeter.javadsl.JmeterDsl.*;
94+
import us.abstracta.jmeter.javadsl.websocket.DslWebsocketSampler;
95+
import us.abstracta.jmeter.javadsl.core.TestPlanStats;
96+
97+
public class Test {
98+
public static void main(String[] args) throws Exception {
99+
TestPlanStats stats = testPlan(
100+
threadGroup(1, 1,
101+
// Connect to WebSocket server
102+
DslWebsocketSampler
103+
.connect("wss://ws.postman-echo.com/raw")
104+
.connectionTimeout("10000")
105+
.responseTimeout("5000"),
106+
107+
// Send a message
108+
DslWebsocketSampler
109+
.write()
110+
.requestData("Hello WebSocket!")
111+
.createNewConnection(false),
112+
113+
// Read the response
114+
DslWebsocketSampler
115+
.read()
116+
.responseTimeout("5000")
117+
.createNewConnection(false)
118+
.children(
119+
responseAssertion()
120+
.equalsToStrings("Hello WebSocket!")
121+
),
122+
123+
// Close the connection
124+
DslWebsocketSampler
125+
.disconnect()
126+
.responseTimeout("1000")
127+
.statusCode("1000")
128+
)
129+
).run();
130+
}
131+
}
132+
```
133+
134+
### Manual Connection Configuration
135+
136+
```java
137+
DslWebsocketSampler
138+
.connect()
139+
.server("localhost")
140+
.port("8080")
141+
.path("/websocket")
142+
.tls(false)
143+
.connectionTimeout("5000")
144+
.responseTimeout("3000")
145+
```
146+
147+
### Connection with Assertions
148+
149+
```java
150+
DslWebsocketSampler
151+
.read()
152+
.responseTimeout("5000")
153+
.createNewConnection(false)
154+
.children(
155+
responseAssertion()
156+
.containsSubstrings("expected response")
157+
)
158+
```
159+
160+
## Error Handling
161+
162+
### Invalid URL Handling
163+
164+
```java
165+
// This will throw IllegalArgumentException
166+
DslWebsocketSampler.connect("http://localhost:80/test");
167+
```
168+
169+
The URL parser validates:
170+
- Protocol must be `ws://` or `wss://`
171+
- Hostname is required
172+
- Valid URI syntax
173+
174+
### Connection Timeouts
175+
176+
Configure appropriate timeouts to handle network issues:
177+
178+
```java
179+
DslWebsocketSampler
180+
.connect("wss://example.com/ws")
181+
.connectionTimeout("10000") // 10 seconds
182+
.responseTimeout("5000") // 5 seconds
183+
```
184+
185+
## Best Practices
186+
187+
1. **Connection Reuse**: Set `createNewConnection(false)` for write/read operations to reuse existing connections
188+
2. **Timeout Configuration**: Always set appropriate timeouts to avoid hanging tests
189+
3. **Error Handling**: Use response assertions to validate WebSocket responses
190+
4. **URL Parsing**: Use the `connect(String url)` method for cleaner code when you have complete URLs
191+
5. **Status Codes**: Use standard WebSocket close codes (1000 for normal closure)
192+
193+
## Integration with Test Plans
194+
195+
WebSocket samplers integrate seamlessly with other JMeter DSL components:
196+
197+
```java
198+
testPlan(
199+
threadGroup(10, 100,
200+
// WebSocket operations
201+
DslWebsocketSampler.connect("wss://api.example.com/ws"),
202+
DslWebsocketSampler.write().requestData("test data"),
203+
DslWebsocketSampler.read(),
204+
DslWebsocketSampler.disconnect(),
205+
),
206+
// Results collection
207+
jtlWriter("results.jtl"),
208+
resultsTreeVisualizer()
209+
)
210+
```

jmeter-java-dsl-cli/pom.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,6 @@
201201
<include>org.apache-extras.beanshell:bsh</include>
202202
<!-- required for converting jsonpath -->
203203
<include>com.jayway.jsonpath:json-path</include>
204-
<!-- required for kotlin support in JMeter 5.6.3+ -->
205204
<include>org.jetbrains.kotlin:kotlin-stdlib</include>
206205
<include>org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm</include>
207206
<include>org.jetbrains.kotlinx:kotlinx-coroutines-swing</include>

jmeter-java-dsl-cli/src/test/java/us/abstracta/jmeter/javadsl/jmx2dsl/Jmx2DslIT.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ public class Jmx2DslIT {
1818
@Test
1919
public void shouldGetConvertedFileWhenConvert() throws Exception {
2020
Process p = startCommand("jmx2dsl", new TestResource("test-plan.jmx").filePath());
21-
assertThat(getProcessOutput(p))
22-
.isEqualTo(buildConvertedTestClass());
21+
assertThat(getProcessOutput(p).replace("\r\n", "\n"))
22+
.isEqualTo(buildConvertedTestClass().replace("\r\n", "\n"));
2323
}
2424

2525
private Process startCommand(String command, String... args) throws IOException {

jmeter-java-dsl-websocket/pom.xml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>us.abstracta.jmeter</groupId>
8+
<artifactId>jmeter-java-dsl-parent</artifactId>
9+
<version>2.2-SNAPSHOT</version>
10+
<relativePath>../pom.xml</relativePath>
11+
</parent>
12+
13+
<groupId>us.abstracta.jmeter.javadsl.websocket</groupId>
14+
<artifactId>jmeter-java-dsl-websocket</artifactId>
15+
16+
<dependencies>
17+
<dependency>
18+
<groupId>us.abstracta.jmeter</groupId>
19+
<artifactId>jmeter-java-dsl</artifactId>
20+
<version>${project.version}</version>
21+
</dependency>
22+
<dependency>
23+
<groupId>net.luminis.jmeter</groupId>
24+
<artifactId>jmeter-websocket-samplers</artifactId>
25+
<version>1.3.1</version>
26+
<exclusions>
27+
<exclusion>
28+
<groupId>org.apache.jmeter</groupId>
29+
<artifactId>ApacheJMeter_core</artifactId>
30+
</exclusion>
31+
<exclusion>
32+
<groupId>org.apache.jmeter</groupId>
33+
<artifactId>jorphan</artifactId>
34+
</exclusion>
35+
</exclusions>
36+
</dependency>
37+
</dependencies>
38+
39+
</project>

0 commit comments

Comments
 (0)