---
title: "Testing in Action"
description: "Before any discovery is introduced to the public, it undergoes various tests. Of course, systems and software developed by developers are no exception to this."
canonical_url: "https://otabek.io/blogs/testing-in-action"
md_url: "https://otabek.io/blogs/testing-in-action.md"
language: "en"
last_updated: "2024-09-16"
tags: ["Backend"]
---

# Testing in Action

Before any discovery is presented to the public, it gets tested over and over again. And guess what? Software is no exception! Today, let's talk about how we make sure our code actually works before we ship it. 🚀

![UI Design vs User Testing](https://miro.medium.com/v2/1*EZvHrZfS_9U5zuIdjdUaPg.jpeg)

### Unit Test

Think of a **Unit** as a tiny piece of your program. When you want to check if that small piece works correctly, you write unit tests for it. Imagine this: you're a teacher with 10,000 students who all submitted homework. Checking all of them by hand? Impossible! But computers can do it in seconds.

Here's a simple example:

```python-run
# Input: join_words("hello", "it's", "me", "Otabek")
# Output: "hello it's me Otabek"
def join_words(*words: tuple[str], sep: str = " ") -> str:
    return sep.join(words)
```

This function takes words and joins them together (you can choose how to separate them with `sep`). Now, how do we test if it works properly? Let's write a unit test:

```python-run
import unittest  # Import unittest - this is like bringing your testing toolbox

class TestJoinWords(unittest.TestCase):  # Create a testing class - think of it as your test paper
    # Methods should start with "test_" - like questions on your test
    def test_simple(self):
        # assertEqual checks if two things match - like comparing answers
        # "When I run the function with these inputs, it should give this result"
        self.assertEqual(join_words("it's", "me"), "it's me")
        self.assertEqual(join_words("testing", "in", "action", sep="-"), "testing-in-action")

if __name__ == '__main__':
    unittest.main()  # This runs all your tests - like submitting your test for grading
```

I recommend exploring unit tests more. They're perfect for testing classes, methods, and functions. They're like your first line of defense against bugs!

### Integration Test

![Integration Test Illustration](https://miro.medium.com/v2/1*5fFw_rC0oi2W6bmVLaX4TQ.jpeg)

Let's say you've built an awesome app that thousands of people love. Now you want to add cool new features. But wait - will these new parts work well with the old ones? That's where **Integration** tests come in!

> The word **Integration** means **joining things together**. So when you add new features to your app, these tests make sure they play nice with everything else.

There are two main types: **Big Bang** tests (testing everything at once - like throwing all your toys in a box and seeing if they fit) and **Incremental** tests (testing small groups of features - like carefully arranging your toys one by one).

Big companies with huge apps usually use the **Incremental** approach because testing everything at once would take forever!

While unit tests check if individual functions work, integration tests make sure they work together as a team. Here's a simple example:

```python-run
# Let's test a mini user information system
def user_info(name: str, age: int) -> dict:
    return {"user": name, "age": age}  # This function creates user data

def display_user_info(data: dict) -> str:
    return f"User {data['user']} is {data['age']} years old."  # This formats the data

def get_user_info(name: str, age: int) -> str:
    data = user_info(name, age)  # Get the data using the first function
    return display_user_info(data)  # Format it using the second function

# Integration test - checking if both functions work together correctly
assert get_user_info("Otabek", 23) == "User Otabek is 23 years old."
assert get_user_info("John", 14) == "User John is 14 years old."
```

### Functional Test

Functional tests answer one simple question: "_Does this thing do what it's supposed to do?_" They focus on whether your app solves real business problems correctly. It's not about HOW it works, but WHETHER it works. Think of it like this: "I don't care how the car engine works, I just want it to take me to the grocery store!" 😄

### E2E (End-to-End) Test

End-to-End means testing the whole journey from start to finish. Think of it like this:

- One **end** is your server (the chef in a restaurant)
- The other **end** is your user (the hungry customer)

E2E tests check if the whole experience works smoothly. It's like having someone secretly test your restaurant by acting like a regular customer - ordering food, paying, and eating - to make sure everything works perfectly from entrance to exit.

These tests pretend to be real users clicking buttons, filling forms, and using your app just like humans would. They're the closest thing to having an army of test users before your real users arrive!

![End-to-End testing meme](https://miro.medium.com/v2/1*c231Y-idAokGRDtV-Hrzyw.png)

### Canary Test

Here's a cool story: miners used to bring canaries (small birds) into mines. If the bird died, it meant the air was poisonous and humans shouldn't go in. If the bird was fine, the miners knew it was safe.

In software, we do something similar! We release new features to a small group of trusted users first. If they find bugs, they tell us and we fix them. If everything works great, we roll it out to everyone. These brave first users are our "canaries" - testing the air before everyone else jumps in!

![Canary test meme](https://testsigma.com/blog/wp-content/uploads/What-is-Canary-Testing-A-Comprehensive-Overview.png)

### Stress Test

Stress testing is like seeing how much your little brother can annoy you before you lose your cool! 😂 You push your system to its limits to see when it breaks.

For example, what happens if a user sends a million requests in a loop? Or tries to upload 50 huge files at once? Will your app crash and burn, or handle it gracefully? Here's a simple stress test:

```python
def test_infinite_loop():
    try:
        while True:  # Keep adding users forever until something breaks
            append_new_users()
    except MemoryError:
        print("Oops! We hit a breaking point!")

def test_heavy_tasks():
    try:
        while True:  # Keep doing hard work until something breaks
            do_heavy_task()
    except MemoryError:
        print("Oops! We hit a breaking point!")
```

### UI Testing

UI tests check if your app's interface looks and works correctly. Is the text showing up? Are buttons the right color? Is everything where it should be? Here's a simple example for a React app:

```js
// Testing if our welcome message appears on screen
import { render, screen } from '@testing-library/react'
import App from './App'

test('shows our welcome message', () => {
  render(<App />) // Display the app
  expect(screen.getByText(/welcome/i)).toBeInTheDocument() // Look for "welcome" text
})
```

### Monkey Test

![Monkey test meme](https://miro.medium.com/v2/1*LWHbxjZhkaGyDPz3JzZ06A.gif)

Ever seen a toddler with a smartphone? They push random buttons, swipe in crazy directions, and do things you'd never expect. That's basically a monkey test! 🐒

This genius test (invented by Netflix) checks what happens when users do unpredictable things. If your app survives a monkey test, it can probably handle anything real users throw at it!

```python-run
import random

def click_button(buttons):
    return random.choice(buttons)  # Pick a random button to press

# Simulating random button presses
buttons = ['Save', 'Cancel', 'Delete']
clicked_button = click_button(buttons)
assert clicked_button in buttons  # We hope this doesn't break our app!
```

This is just a super simple example. Real monkey tests are much wilder!

### Fuzz Testing

Imagine you have a form asking for first and last names. Most people will enter actual names, but some crazy folks might type numbers, weird symbols, or even "👑KING👑".

Fuzz testing throws random, unexpected, or just plain weird data at your program to see if it handles the chaos gracefully. Here's an example in Go:

```go-run
package main

import (
    "fmt"
    "testing"
)

// Function that reverses strings
func Reverse(s string) string {
    runes := []rune(s)
    for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
        runes[i], runes[j] = runes[j], runes[i]
    }
    return string(runes)
}

// Fuzz test function - throws weird inputs at our function
func TestReverse(f *testing.F) {
    testCases := []string{"hello", "world", "", "a", "racecar", "Go is fun!"}
    for _, tc := testCases {
        f.Add(tc)
    }

    f.Fuzz(func(t *testing.T, input string) {
        reversed := Reverse(input)
        doubleReversed := Reverse(reversed)
        if input != doubleReversed {
            t.Errorf("Expected %q but got %q", input, doubleReversed)
        }
        if len(reversed) != len(input) {
            t.Errorf("LengthError: input length %d, reversed length %d", len(input), len(reversed))
        }
    })
}

func main() {
    fmt.Println("Run `go test` to execute fuzz testing.")
}
```

### Others

There are tons of other test types out there! In this article, I've covered some of the most common ones with examples you can actually understand (I hope!).

We might talk about **regression tests**, **security tests**, **A-B tests**, **smoke tests**, **load tests**, **performance tests**, **acceptance tests**, and more in future posts. Testing might sound boring, but it's actually what keeps the digital world from falling apart! 🌎

---

```quiz
{
  "quiz": {
    "id": "testing-quiz",
    "title": "Software Testing Quiz",
    "description": "Test your understanding of different testing types",
    "questions": [
      {
        "id": "q1",
        "type": "single-choice",
        "question": "What does a Unit Test test?",
        "options": [
          { "id": "a", "text": "A small, isolated piece of code like a function", "description": "" },
          { "id": "b", "text": "The entire application", "description": "That's more like E2E testing. Unit tests focus on small pieces." },
          { "id": "c", "text": "The user interface only", "description": "UI testing is separate. Unit tests focus on code logic." },
          { "id": "d", "text": "The database", "description": "Database testing is different. Unit tests focus on code units." }
        ]
      },
      {
        "id": "q2",
        "type": "single-choice",
        "question": "What does Integration Testing verify?",
        "options": [
          { "id": "a", "text": "That individual functions work", "description": "That's unit testing. Integration tests check how parts work together." },
          { "id": "b", "text": "That different parts of the system work together", "description": "" },
          { "id": "c", "text": "The UI looks correct", "description": "UI testing is different from integration testing." },
          { "id": "d", "text": "The system handles stress", "description": "That's stress testing, not integration testing." }
        ]
      },
      {
        "id": "q3",
        "type": "drag-drop",
        "question": "Order these tests from smallest scope to largest:",
        "items": [
          { "id": "unit", "content": "Unit Test" },
          { "id": "integration", "content": "Integration Test" },
          { "id": "e2e", "content": "End-to-End Test" }
        ]
      },
      {
        "id": "q4",
        "type": "single-choice",
        "question": "What is a Canary Test named after?",
        "options": [
          { "id": "a", "text": "Canaries used in mines to detect danger", "description": "" },
          { "id": "b", "text": "The Canary Islands", "description": "It's named after the mining practice of using canaries." },
          { "id": "c", "text": "A famous developer named Canary", "description": "It's named after canaries used to detect toxic gases in mines." },
          { "id": "d", "text": "The yellow color of warning signs", "description": "It comes from mining canaries, not colors." }
        ]
      },
      {
        "id": "q5",
        "type": "single-choice",
        "question": "What is the purpose of Stress Testing?",
        "options": [
          { "id": "a", "text": "To see how the system behaves under extreme load", "description": "" },
          { "id": "b", "text": "To check if developers are stressed", "description": "Stress testing is about system load, not people!" },
          { "id": "c", "text": "To test the UI design", "description": "UI testing is separate from stress testing." },
          { "id": "d", "text": "To verify individual functions", "description": "That's unit testing. Stress testing checks system limits." }
        ]
      },
      {
        "id": "q6",
        "type": "multiple-choice",
        "question": "What does Monkey Testing involve? (Select all that apply)",
        "options": [
          { "id": "a", "text": "Random, unpredictable user actions", "description": "" },
          { "id": "b", "text": "Testing with actual monkeys", "description": "It's about random behavior, not real monkeys!" },
          { "id": "c", "text": "Pressing random buttons", "description": "" },
          { "id": "d", "text": "Doing things users wouldn't normally do", "description": "" }
        ]
      }
    ]
  },
  "answers": {
    "q1": { "correctOptionIds": ["a"] },
    "q2": { "correctOptionIds": ["b"] },
    "q3": { "correctOrder": ["unit", "integration", "e2e"] },
    "q4": { "correctOptionIds": ["a"] },
    "q5": { "correctOptionIds": ["a"] },
    "q6": { "correctOptionIds": ["a", "c", "d"] }
  }
}
```


## Sitemap

See the full [Markdown sitemap](/sitemap.md) for all pages.
