|
1 | | -# Qtest - HTTP Testing Utility for Quick Framework |
| 1 | +# 🧪 Qtest - HTTP Testing Utility for Quick Framework  |
2 | 2 |
|
3 | 3 | Qtest is an **advanced HTTP testing function** designed to simplify route validation within the **Quick** framework. It enables seamless testing of simulated HTTP requests using `httptest`, supporting: |
4 | 4 |
|
@@ -122,8 +122,12 @@ func (qt *qTestPlus) AssertBodyContains(expected string) error { |
122 | 122 | ``` |
123 | 123 |
|
124 | 124 | ## 📌 Example Usage in a Test |
| 125 | + |
| 126 | +✅ Test POST Request |
| 127 | + |
125 | 128 | Here's an example of how to use `Qtest` to test an API receiving a `POST` request. |
126 | 129 |
|
| 130 | + |
127 | 131 | ```go |
128 | 132 | func TestQTest_Options_POST(t *testing.T) { |
129 | 133 | q := New() |
@@ -173,12 +177,278 @@ func TestQTest_Options_POST(t *testing.T) { |
173 | 177 | } |
174 | 178 | ``` |
175 | 179 |
|
176 | | -## 🔥 Conclusion |
177 | | -`Qtest` is a powerful tool for testing in the **Quick** framework, simplifying API validation. It allows: |
178 | | -✅ Testing any **HTTP method**. |
179 | | -✅ Easily adding **headers, cookies, and query parameters**. |
180 | | -✅ **Validating status, headers, and response bodies** intuitively. |
181 | | -✅ **Enabling detailed logs** for debugging. |
| 180 | +✅ Test GET Request |
| 181 | + |
| 182 | +Tests a basic `GET` request to ensure the correct response status and body content. |
| 183 | + |
| 184 | +```go |
| 185 | +func TestQTest_Options_GET(t *testing.T) { |
| 186 | + |
| 187 | + q := New() |
| 188 | + |
| 189 | + q.Get("/v1/user", func(c *Ctx) error { |
| 190 | + c.Set("Content-Type", "application/json") |
| 191 | + return c.Status(StatusOK).String("Success") |
| 192 | + }) |
| 193 | + |
| 194 | + opts := QuickTestOptions{ |
| 195 | + Method: "GET", |
| 196 | + URI: "/v1/user", |
| 197 | + Headers: map[string]string{"Accept": "application/json"}, |
| 198 | + LogDetails: true, |
| 199 | + } |
| 200 | + |
| 201 | + result, err := q.Qtest(opts) |
| 202 | + if err != nil { |
| 203 | + t.Fatalf("Error in test: %v", err) |
| 204 | + } |
| 205 | + |
| 206 | + if err := result.AssertStatus(StatusOK); err != nil { |
| 207 | + t.Errorf("Status assertion failed: %v", err) |
| 208 | + } |
| 209 | + |
| 210 | + // Debug the response body for troubleshooting |
| 211 | + fmt.Println("DEBUG Body (QTest):", result.BodyStr()) |
| 212 | + |
| 213 | + if err := result.AssertBodyContains("Success"); err != nil { |
| 214 | + t.Errorf("Body assertion failed: %v", err) |
| 215 | + } |
| 216 | +} |
| 217 | + |
| 218 | +``` |
| 219 | + |
| 220 | +✅ Test POST Request |
| 221 | + |
| 222 | +Validates a `POST` request with headers, query parameters, and body content. |
| 223 | + |
| 224 | +```go |
| 225 | +func TestQTest_Options_POST(t *testing.T) { |
| 226 | + |
| 227 | + q := New() |
| 228 | + |
| 229 | + q.Post("/v1/user/api", func(c *Ctx) error { |
| 230 | + c.Set("Content-Type", "application/json") |
| 231 | + c.Response.Header().Set("Content-Type", "application/json") |
| 232 | + return c.Status(StatusOK).String(`{"message":"Success"}`) |
| 233 | + }) |
| 234 | + |
| 235 | + opts := QuickTestOptions{ |
| 236 | + Method: "POST", // Correct method |
| 237 | + URI: "/v1/user/api", |
| 238 | + QueryParams: map[string]string{ |
| 239 | + "param1": "value1", |
| 240 | + "param2": "value2", |
| 241 | + }, |
| 242 | + Body: []byte(`{"key":"value"}`), |
| 243 | + Headers: map[string]string{ |
| 244 | + "Content-Type": "application/json", |
| 245 | + }, |
| 246 | + Cookies: []*http.Cookie{ |
| 247 | + {Name: "session", Value: "abc123"}, |
| 248 | + }, |
| 249 | + LogDetails: true, // Enable the log for debug |
| 250 | + } |
| 251 | + |
| 252 | + // Runs the test |
| 253 | + result, err := q.Qtest(opts) |
| 254 | + if err != nil { |
| 255 | + t.Fatalf("Error in Qtest: %v", err) |
| 256 | + } |
| 257 | + |
| 258 | + // Check if the status is correct |
| 259 | + if err := result.AssertStatus(StatusOK); err != nil { |
| 260 | + t.Errorf("Status assertion failed: %v", err) |
| 261 | + } |
| 262 | + |
| 263 | + // Check if o Expected header is present |
| 264 | + if err := result.AssertHeader("Content-Type", "application/json"); err != nil { |
| 265 | + t.Errorf("Header assertion failed: %v", err) |
| 266 | + } |
| 267 | + |
| 268 | + // Check if the answer contains "Success" |
| 269 | + if err := result.AssertBodyContains("Success"); err != nil { |
| 270 | + t.Errorf("Body assertion failed: %v", err) |
| 271 | + } |
| 272 | +} |
| 273 | + |
| 274 | +``` |
| 275 | + |
| 276 | + |
| 277 | +✅ Test PUT Request |
| 278 | + |
| 279 | +Checks if a PUT request correctly updates user data. |
| 280 | +```go |
| 281 | +func TestQTest_Options_PUT(t *testing.T) { |
| 282 | + q := New() |
| 283 | + |
| 284 | + // Define the PUT route |
| 285 | + q.Put("/v1/user/update", func(c *Ctx) error { |
| 286 | + c.Set("Content-Type", "application/json") |
| 287 | + return c.Status(StatusOK).String(`{"message":"User updated successfully"}`) |
| 288 | + }) |
| 289 | + |
| 290 | + opts := QuickTestOptions{ |
| 291 | + Method: "PUT", |
| 292 | + URI: "/v1/user/update", |
| 293 | + Body: []byte(`{"name":"Jeff Quick","age":30}`), |
| 294 | + Headers: map[string]string{ |
| 295 | + "Content-Type": "application/json", |
| 296 | + }, |
| 297 | + LogDetails: true, |
| 298 | + } |
| 299 | + |
| 300 | + result, err := q.Qtest(opts) |
| 301 | + if err != nil { |
| 302 | + t.Fatalf("Error in Qtest: %v", err) |
| 303 | + } |
| 304 | + |
| 305 | + if err := result.AssertStatus(StatusOK); err != nil { |
| 306 | + t.Errorf("Status assertion failed: %v", err) |
| 307 | + } |
| 308 | + |
| 309 | + if err := result.AssertBodyContains(`"message":"User updated successfully"`); err != nil { |
| 310 | + t.Errorf("Body assertion failed: %v", err) |
| 311 | + } |
| 312 | +} |
| 313 | + |
| 314 | +``` |
| 315 | + |
| 316 | +✅ Test DELETE Request |
| 317 | + |
| 318 | +Ensures that a DELETE request successfully removes a user entry. |
| 319 | +```go |
| 320 | +func TestQTest_Options_DELETE(t *testing.T) { |
| 321 | + q := New() |
| 322 | + |
| 323 | + // Define the DELETE route |
| 324 | + q.Delete("/v1/user/delete", func(c *Ctx) error { |
| 325 | + c.Set("Content-Type", "application/json") |
| 326 | + return c.Status(StatusOK).String(`{"message":"User deleted successfully"}`) |
| 327 | + }) |
| 328 | + |
| 329 | + opts := QuickTestOptions{ |
| 330 | + Method: "DELETE", |
| 331 | + URI: "/v1/user/delete", |
| 332 | + LogDetails: true, |
| 333 | + } |
| 334 | + |
| 335 | + result, err := q.Qtest(opts) |
| 336 | + if err != nil { |
| 337 | + t.Fatalf("Error in Qtest: %v", err) |
| 338 | + } |
| 339 | + |
| 340 | + if err := result.AssertStatus(StatusOK); err != nil { |
| 341 | + t.Errorf("Status assertion failed: %v", err) |
| 342 | + } |
| 343 | + |
| 344 | + if err := result.AssertBodyContains(`"message":"User deleted successfully"`); err != nil { |
| 345 | + t.Errorf("Body assertion failed: %v", err) |
| 346 | + } |
| 347 | +} |
| 348 | + |
| 349 | +``` |
| 350 | + |
| 351 | +✅ Test PATCH Request |
| 352 | + |
| 353 | +Verifies partial updates to user data using a PATCH request. |
| 354 | +```go |
| 355 | +func TestQTest_Options_PATCH(t *testing.T) { |
| 356 | + q := New() |
| 357 | + |
| 358 | + // Define the PATCH route |
| 359 | + q.Patch("/v1/user/patch", func(c *Ctx) error { |
| 360 | + c.Set("Content-Type", "application/json") |
| 361 | + return c.Status(StatusOK).String(`{"message":"User patched successfully"}`) |
| 362 | + }) |
| 363 | + |
| 364 | + opts := QuickTestOptions{ |
| 365 | + Method: "PATCH", |
| 366 | + URI: "/v1/user/patch", |
| 367 | + Body: []byte(`{"nickname":"Johnny"}`), |
| 368 | + Headers: map[string]string{ |
| 369 | + "Content-Type": "application/json", |
| 370 | + }, |
| 371 | + LogDetails: true, |
| 372 | + } |
| 373 | + |
| 374 | + result, err := q.Qtest(opts) |
| 375 | + if err != nil { |
| 376 | + t.Fatalf("Error in Qtest: %v", err) |
| 377 | + } |
| 378 | + |
| 379 | + if err := result.AssertStatus(StatusOK); err != nil { |
| 380 | + t.Errorf("Status assertion failed: %v", err) |
| 381 | + } |
| 382 | + |
| 383 | + if err := result.AssertBodyContains(`"message":"User patched successfully"`); err != nil { |
| 384 | + t.Errorf("Body assertion failed: %v", err) |
| 385 | + } |
| 386 | +} |
| 387 | + |
| 388 | +``` |
| 389 | + |
| 390 | +✅ Test OPTIONS Request |
| 391 | + |
| 392 | +Confirms the allowed HTTP methods for a given route. |
| 393 | +```go |
| 394 | +func TestQTest_Options_OPTIONS(t *testing.T) { |
| 395 | + q := New() |
| 396 | + |
| 397 | + // Define the OPTIONS route |
| 398 | + q.Options("/v1/user/options", func(c *Ctx) error { |
| 399 | + c.Set("Allow", "GET, POST, PUT, DELETE, OPTIONS") |
| 400 | + return c.Status(StatusNoContent).String("") |
| 401 | + }) |
| 402 | + |
| 403 | + opts := QuickTestOptions{ |
| 404 | + Method: "OPTIONS", |
| 405 | + URI: "/v1/user/options", |
| 406 | + LogDetails: true, |
| 407 | + } |
| 408 | + |
| 409 | + result, err := q.Qtest(opts) |
| 410 | + if err != nil { |
| 411 | + t.Fatalf("Error in Qtest: %v", err) |
| 412 | + } |
| 413 | + |
| 414 | + if err := result.AssertStatus(StatusNoContent); err != nil { |
| 415 | + t.Errorf("Status assertion failed: %v", err) |
| 416 | + } |
| 417 | + |
| 418 | + if err := result.AssertHeader("Allow", "GET, POST, PUT, DELETE, OPTIONS"); err != nil { |
| 419 | + t.Errorf("Header assertion failed: %v", err) |
| 420 | + } |
| 421 | +} |
| 422 | + |
| 423 | +``` |
| 424 | +--- |
| 425 | + |
| 426 | +## 📌 What I included in this README |
| 427 | + |
| 428 | +- ✅ **README checklist** - Overview of Qtest functionalities. |
| 429 | +- ✅ **Overview**: Explanation of Qtest and its use in Quick framework. |
| 430 | +- ✅ **Core Function**: Detailed implementation of Qtest function. |
| 431 | +- ✅ **Input & Output Structures**: Explanation of `QuickTestOptions` and `QtestReturn`. |
| 432 | +- ✅ **Validation Methods**: Methods for checking status, headers, and response bodies. |
| 433 | + |
| 434 | +### ✅ Example Test Cases: |
| 435 | +- ✅ **GET** request validation. |
| 436 | +- ✅ **POST** request validation with headers and query params. |
| 437 | +- ✅ **PUT** request validation for updating user data. |
| 438 | +- ✅ **DELETE** request validation for removing a user. |
| 439 | +- ✅ **PATCH** request validation for partial updates. |
| 440 | +- ✅ **OPTIONS** request validation for checking allowed methods. |
| 441 | + |
| 442 | +### ✅ Testing Checklist: |
| 443 | +- ✅ Coverage for HTTP methods. |
| 444 | +- ✅ Validation of status codes, headers, and response bodies. |
| 445 | +- ✅ Error handling and invalid input cases. |
| 446 | +- ✅ Organization and optimization of tests. |
| 447 | + |
| 448 | +- ✅ **Conclusion**: Summary of Qtest benefits and call for contributions. |
| 449 | + |
| 450 | + |
| 451 | +--- |
182 | 452 |
|
183 | 453 | With this approach, tests become more structured and maintainable. 🚀🔥 |
184 | 454 |
|
|
0 commit comments