<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dhruv Patel</title>
    <description>The latest articles on DEV Community by Dhruv Patel (@dhruvtechdev).</description>
    <link>https://dev.to/dhruvtechdev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4001416%2F08a82fac-ab6b-4f8a-b823-7aef49d0ae6e.png</url>
      <title>DEV Community: Dhruv Patel</title>
      <link>https://dev.to/dhruvtechdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dhruvtechdev"/>
    <language>en</language>
    <item>
      <title>How Developers Think About Software Testing in the AI Era</title>
      <dc:creator>Dhruv Patel</dc:creator>
      <pubDate>Sat, 15 Aug 2026 14:23:27 +0000</pubDate>
      <link>https://dev.to/dhruvtechdev/how-developers-should-think-about-software-testing-in-the-ai-era-5ap7</link>
      <guid>https://dev.to/dhruvtechdev/how-developers-should-think-about-software-testing-in-the-ai-era-5ap7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Writing code is only half the job. The other half is proving that it behaves the way you think it does — especially when everything goes wrong.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What if your code looks perfect, passes every test you wrote, gets a green CI check...&lt;/p&gt;

&lt;p&gt;and is still wrong?&lt;/p&gt;

&lt;p&gt;That question becomes even more interesting now that AI can generate functions, APIs, tests, mocks, documentation, and sometimes entire features in minutes.&lt;/p&gt;

&lt;p&gt;Software development is becoming faster.&lt;/p&gt;

&lt;p&gt;But faster code generation does not automatically mean safer software.&lt;/p&gt;

&lt;p&gt;In fact, it might make good testing more important than ever.&lt;/p&gt;

&lt;p&gt;Because this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Code compiles ✅
Tests pass ✅
Coverage: 95% ✅
CI pipeline: Green ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;does not necessarily mean this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The software is correct ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A test suite can pass while missing the exact scenario that breaks your application in production.&lt;/p&gt;

&lt;p&gt;So I decided to dive deeper into software testing — not just how to write a unit test, but how testing actually fits into software engineering.&lt;/p&gt;

&lt;p&gt;And the biggest realization was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Testing is not about proving that your software works.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is about finding situations where your assumptions stop being true.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Software Testing?
&lt;/h2&gt;

&lt;p&gt;Software testing is the process of checking whether software behaves as expected and identifying situations where it does not.&lt;/p&gt;

&lt;p&gt;Imagine we build this function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test passes.&lt;/p&gt;

&lt;p&gt;Great.&lt;/p&gt;

&lt;p&gt;But what about:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suddenly the problem becomes more interesting.&lt;/p&gt;

&lt;p&gt;Testing is not just asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does this work?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Under what conditions does this stop working?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That difference is huge.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Testing Matters
&lt;/h2&gt;

&lt;p&gt;Imagine deploying an e-commerce application.&lt;/p&gt;

&lt;p&gt;Everything appears fine during development.&lt;/p&gt;

&lt;p&gt;Then production traffic arrives.&lt;/p&gt;

&lt;p&gt;A user adds two items to the cart.&lt;/p&gt;

&lt;p&gt;Another request updates inventory at the same time.&lt;/p&gt;

&lt;p&gt;Payment succeeds.&lt;/p&gt;

&lt;p&gt;Inventory fails.&lt;/p&gt;

&lt;p&gt;The customer gets charged...&lt;/p&gt;

&lt;p&gt;but no order is created.&lt;/p&gt;

&lt;p&gt;Now we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a frustrated customer&lt;/li&gt;
&lt;li&gt;inconsistent database state&lt;/li&gt;
&lt;li&gt;support tickets&lt;/li&gt;
&lt;li&gt;refund operations&lt;/li&gt;
&lt;li&gt;debugging time&lt;/li&gt;
&lt;li&gt;potentially lost trust&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A small bug can become an expensive business problem.&lt;/p&gt;

&lt;p&gt;That leads to an important principle:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The earlier you discover a defect, the easier and cheaper it generally is to fix.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Finding a problem while writing a function is much easier than discovering it after thousands of users have interacted with the system.&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing vs Debugging
&lt;/h2&gt;

&lt;p&gt;These terms are related, but they are not the same thing.&lt;/p&gt;

&lt;p&gt;Testing finds failures.&lt;/p&gt;

&lt;p&gt;Debugging investigates why those failures happen.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Test:
Checkout fails when quantity = 0.

Debugging:
Developer discovers the backend accepts negative inventory.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Testing answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Something is wrong.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Debugging answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Here is why it is wrong.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Verification vs Validation
&lt;/h2&gt;

&lt;p&gt;Another distinction I used to mix up:&lt;/p&gt;

&lt;p&gt;Verification asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Are we building the product correctly?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Validation asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Are we building the correct product?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Imagine the requirement says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Passwords must contain at least 8 characters.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your implementation correctly rejects seven-character passwords.&lt;/p&gt;

&lt;p&gt;That is verification.&lt;/p&gt;

&lt;p&gt;But what if the actual business requirement should have been:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Passwords must contain at least 12 characters.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your code correctly implemented the wrong requirement.&lt;/p&gt;

&lt;p&gt;That becomes a validation problem.&lt;/p&gt;

&lt;p&gt;A technically perfect implementation can still solve the wrong problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing Cannot Prove That Bugs Don't Exist
&lt;/h2&gt;

&lt;p&gt;This is probably one of the most important principles in testing.&lt;/p&gt;

&lt;p&gt;Suppose your application has 20,000 tests.&lt;/p&gt;

&lt;p&gt;Every test passes.&lt;/p&gt;

&lt;p&gt;Can you say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This software contains zero bugs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;Tests can demonstrate the presence of defects.&lt;/p&gt;

&lt;p&gt;They cannot prove their complete absence.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because exhaustive testing is generally impossible.&lt;/p&gt;

&lt;p&gt;Consider a simple text input.&lt;/p&gt;

&lt;p&gt;Possible variables include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Length
Characters
Encoding
Language
Whitespace
Special characters
Emoji
Null values
Extremely large values
Malicious input
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Multiply that by:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browsers
Operating systems
Network conditions
Permissions
Database states
User states
Concurrent requests
Third-party services
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The number of possible combinations becomes enormous.&lt;/p&gt;

&lt;p&gt;Testing therefore becomes a problem of intelligent risk selection.&lt;/p&gt;




&lt;h2&gt;
  
  
  Think Like a Breaker
&lt;/h2&gt;

&lt;p&gt;Developers naturally think:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;How can I make this work?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Testing introduces another mindset:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;How can I make this fail?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suppose we're testing login.&lt;/p&gt;

&lt;p&gt;Most developers start here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Valid email
+
Valid password
=
Login succeeds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A tester starts asking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What if the password is wrong?

What if the account is locked?

What if the email doesn't exist?

What if the password is empty?

What if the database is unavailable?

What if the authentication service times out?

What if 50,000 users log in simultaneously?

What if the access token is expired?

What if someone modifies the token?

What if one user tries accessing another user's account?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we're testing software.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Different Levels of Testing
&lt;/h2&gt;

&lt;p&gt;Testing is not one giant activity.&lt;/p&gt;

&lt;p&gt;Different tests protect different layers of your system.&lt;/p&gt;

&lt;p&gt;The major levels include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unit Testing
Integration Testing
System Testing
Acceptance Testing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in real projects you will also encounter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Smoke Testing
Sanity Testing
Regression Testing
Component Testing
API Testing
Contract Testing
End-to-End Testing
Alpha Testing
Beta Testing
User Acceptance Testing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down the most important ones.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Unit Testing
&lt;/h3&gt;

&lt;p&gt;Unit tests validate small pieces of software independently.&lt;/p&gt;

&lt;p&gt;A unit might be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Function
Method
Class
Small module
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculateDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;percentage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;percentage&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A unit test could look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;applies a 20% discount&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculateDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple.&lt;/p&gt;

&lt;p&gt;Fast.&lt;/p&gt;

&lt;p&gt;Easy to understand.&lt;/p&gt;

&lt;p&gt;But we shouldn't stop there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;handles zero discount&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculateDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;handles zero price&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculateDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on our requirements, we might also test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Negative price
Negative percentage
Discount &amp;gt; 100%
Non-numeric values
Null
Undefined
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Good unit tests should generally be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fast
Independent
Deterministic
Readable
Self-validating
Focused
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Arrange → Act → Assert
&lt;/h4&gt;

&lt;p&gt;One of the easiest ways to structure tests is AAA.&lt;/p&gt;

&lt;h5&gt;
  
  
  Arrange
&lt;/h5&gt;

&lt;p&gt;Prepare everything needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;discount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Act
&lt;/h5&gt;

&lt;p&gt;Execute the behavior.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculateDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;discount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Assert
&lt;/h5&gt;

&lt;p&gt;Verify the result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Complete test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;applies discount correctly&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Arrange&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;discount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Act&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculateDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;discount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Assert&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another popular format is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Given
When
Then
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll come back to that when discussing BDD.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Integration Testing
&lt;/h3&gt;

&lt;p&gt;Unit tests might prove that components work individually.&lt;/p&gt;

&lt;p&gt;But production systems aren't made of isolated components.&lt;/p&gt;

&lt;p&gt;They communicate.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Controller
    ↓
Service
    ↓
Repository
    ↓
Database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every piece could work independently.&lt;/p&gt;

&lt;p&gt;Yet this connection could still be broken:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Service → Database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maybe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the SQL query is incorrect&lt;/li&gt;
&lt;li&gt;schema names changed&lt;/li&gt;
&lt;li&gt;serialization is wrong&lt;/li&gt;
&lt;li&gt;transaction logic fails&lt;/li&gt;
&lt;li&gt;credentials are incorrect&lt;/li&gt;
&lt;li&gt;connection pooling behaves differently&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Integration testing verifies that components work together correctly.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;creates a user in the database&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dhruv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dhruv@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dhruv@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeDefined&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we're testing more than one function.&lt;/p&gt;

&lt;p&gt;We're checking the interaction between:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP layer
Application logic
Database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. API Testing
&lt;/h3&gt;

&lt;p&gt;API testing deserves special attention because APIs often sit at the boundaries between systems.&lt;/p&gt;

&lt;p&gt;Imagine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /api/orders
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A weak test checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Status = 201
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A stronger test checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Correct status?
Correct response body?
Correct schema?
Correct headers?
Order stored?
Authentication enforced?
Authorization enforced?
Invalid input rejected?
Duplicate request handled?
Rate limit enforced?
Errors formatted correctly?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/orders&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;orderId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then negative tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;No token → 401

Wrong permission → 403

Product missing → 404

Quantity = 0 → 400

Malformed body → 400
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then boundaries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;quantity = 1

quantity = maximum allowed

quantity &amp;gt; maximum allowed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then behavior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Product out of stock

Payment rejected

Database unavailable

Duplicate order request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test surface grows quickly.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. End-to-End Testing
&lt;/h3&gt;

&lt;p&gt;End-to-end testing checks complete workflows from the user's perspective.&lt;/p&gt;

&lt;p&gt;Imagine an online store.&lt;/p&gt;

&lt;p&gt;A critical journey might be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User opens site
        ↓
Searches product
        ↓
Opens product
        ↓
Adds product to cart
        ↓
Logs in
        ↓
Checks out
        ↓
Makes payment
        ↓
Receives confirmation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An E2E test might use Playwright:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user can complete checkout&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByPlaceholder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Search&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Keyboard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mechanical Keyboard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Add to cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mechanical Keyboard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeVisible&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tools commonly used include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Playwright
Cypress
Selenium
Puppeteer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E2E testing gives strong confidence.&lt;/p&gt;

&lt;p&gt;But it comes with costs.&lt;/p&gt;

&lt;p&gt;E2E tests tend to be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Slower
More expensive
More brittle
Harder to debug
More dependent on environment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's why writing 10,000 E2E tests usually isn't the answer.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Testing Pyramid
&lt;/h2&gt;

&lt;p&gt;This gives us one of the most popular testing models:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;             /\
            /  \
           / E2E\
          /------\
         /        \
        /Integration\
       /------------\
      /              \
     /   Unit Tests   \
    /__________________\
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The basic philosophy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Many unit tests
Some integration tests
Few E2E tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because unit tests are usually cheap and fast.&lt;/p&gt;

&lt;p&gt;Integration tests provide deeper confidence but require more resources.&lt;/p&gt;

&lt;p&gt;E2E tests exercise realistic behavior but are expensive.&lt;/p&gt;

&lt;p&gt;A healthy strategy tries to get maximum confidence without making every commit take 45 minutes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Smoke Testing vs Sanity Testing
&lt;/h2&gt;

&lt;p&gt;These two are easy to confuse.&lt;/p&gt;

&lt;p&gt;Smoke testing asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is the important functionality alive at all?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After deployment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application loads ✅
Login works ✅
Database reachable ✅
Critical API works ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If smoke testing fails, there is little reason to continue deeper testing.&lt;/p&gt;

&lt;p&gt;Sanity testing is narrower.&lt;/p&gt;

&lt;p&gt;It asks whether a particular change appears to work.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Developer fixes password reset.

Sanity test:
Does password reset now work?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Smoke → Broad and shallow

Sanity → Narrow and focused
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Regression Testing
&lt;/h2&gt;

&lt;p&gt;You fix Bug #427:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Users with apostrophes in their names cannot register.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You add a test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allows apostrophes in user names&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validateName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;O'Connor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Six months later, another developer changes the validator.&lt;/p&gt;

&lt;p&gt;If the bug returns, the test catches it.&lt;/p&gt;

&lt;p&gt;That is the heart of regression testing.&lt;/p&gt;

&lt;p&gt;Regression testing asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Did the new change break something that previously worked?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And there is a powerful engineering habit hidden here:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every important production bug should ideally leave behind a regression test.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The application shouldn't just get fixed.&lt;/p&gt;

&lt;p&gt;The test suite should get smarter.&lt;/p&gt;




&lt;h2&gt;
  
  
  Test Doubles: Dummy vs Stub vs Spy vs Mock vs Fake
&lt;/h2&gt;

&lt;p&gt;This area confused me at first because people often use "mock" for everything.&lt;/p&gt;

&lt;p&gt;But these concepts have slightly different purposes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dummy
&lt;/h3&gt;

&lt;p&gt;An object passed simply because something requires it.&lt;/p&gt;

&lt;p&gt;It isn't actually used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dummyLogger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Stub
&lt;/h3&gt;

&lt;p&gt;Provides predefined responses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;findById&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dhruv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Spy
&lt;/h3&gt;

&lt;p&gt;Records interactions.&lt;/p&gt;

&lt;p&gt;You might ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Was this function called?

How many times?

With which arguments?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Mock
&lt;/h3&gt;

&lt;p&gt;Usually includes expectations about interactions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Fake
&lt;/h3&gt;

&lt;p&gt;A working but simplified implementation.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Production → PostgreSQL

Testing → In-memory database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test doubles are useful.&lt;/p&gt;

&lt;p&gt;But they introduce one of the most dangerous testing traps.&lt;/p&gt;




&lt;h2&gt;
  
  
  Over-Mocking
&lt;/h2&gt;

&lt;p&gt;Imagine your real payment provider responds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payment_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"abc123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"approved"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But your mock returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"abc123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your tests pass.&lt;/p&gt;

&lt;p&gt;Your production integration fails.&lt;/p&gt;

&lt;p&gt;Beautiful.&lt;/p&gt;

&lt;p&gt;You successfully tested a service that does not exist.&lt;/p&gt;

&lt;p&gt;This is why:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The more mocks you use, the more careful you must be that your simulated world still resembles reality.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mocks are tools.&lt;/p&gt;

&lt;p&gt;Not proof.&lt;/p&gt;




&lt;h2&gt;
  
  
  Test-Driven Development
&lt;/h2&gt;

&lt;p&gt;TDD follows a famous cycle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RED
 ↓
GREEN
 ↓
REFACTOR
 ↺
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Red
&lt;/h3&gt;

&lt;p&gt;Write a failing test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;adds two numbers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no implementation yet.&lt;/p&gt;

&lt;p&gt;Test fails.&lt;/p&gt;

&lt;h3&gt;
  
  
  Green
&lt;/h3&gt;

&lt;p&gt;Write the smallest implementation needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test passes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Refactor
&lt;/h3&gt;

&lt;p&gt;Improve the implementation while keeping the test green.&lt;/p&gt;

&lt;p&gt;TDD isn't necessarily about having maximum tests.&lt;/p&gt;

&lt;p&gt;Its deeper benefit is forcing you to think about behavior before implementation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Behavior-Driven Development
&lt;/h2&gt;

&lt;p&gt;BDD shifts the language toward behavior.&lt;/p&gt;

&lt;p&gt;Instead of thinking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What function should I test?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we describe expected system behavior.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gherkin"&gt;&lt;code&gt;&lt;span class="kd"&gt;Feature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; Shopping Cart

&lt;span class="kn"&gt;Scenario&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; Add product to cart
  &lt;span class="nf"&gt;Given &lt;/span&gt;the user has an empty cart
  &lt;span class="nf"&gt;When &lt;/span&gt;the user adds a keyboard
  &lt;span class="nf"&gt;Then &lt;/span&gt;the cart should contain 1 keyboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Given → Context

When → Action

Then → Expected outcome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can help bridge communication between:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Developers
QA engineers
Product owners
Business stakeholders
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tools include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cucumber
Behave
SpecFlow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One of BDD's interesting ideas is that well-written scenarios can become living documentation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Positive Testing vs Negative Testing
&lt;/h2&gt;

&lt;p&gt;Positive testing asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does the system work with valid input?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Valid email
Valid password
→ Login succeeds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Negative testing asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does the system behave correctly with invalid or unexpected input?&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Wrong password
→ Login rejected
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But negative testing goes much further:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Empty password

Extremely long password

Malformed request

Invalid token

Expired token

Missing database field

Duplicate request

Unexpected content type
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where many interesting bugs live.&lt;/p&gt;

&lt;p&gt;The happy path tells you the feature works.&lt;/p&gt;

&lt;p&gt;Negative testing tells you whether the feature survives reality.&lt;/p&gt;




&lt;h2&gt;
  
  
  Boundary Value Testing
&lt;/h2&gt;

&lt;p&gt;Suppose an API accepts age:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;18 ≤ age ≤ 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Testing this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;age = 50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is useful.&lt;/p&gt;

&lt;p&gt;But these values are often more interesting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;17 ❌

18 ✅

19 ✅

99 ✅

100 ✅

101 ❌
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because defects frequently appear around boundaries.&lt;/p&gt;

&lt;p&gt;The same concept applies to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Array size

Character limits

Pagination

Rate limits

Upload sizes

Price ranges

Dates

Memory limits
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Performance Testing
&lt;/h2&gt;

&lt;p&gt;Your API can be logically correct and still be unusable.&lt;/p&gt;

&lt;p&gt;Suppose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /products
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;returns the correct products.&lt;/p&gt;

&lt;p&gt;But:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Response time = 12 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Functionally correct?&lt;/p&gt;

&lt;p&gt;Yes.&lt;/p&gt;

&lt;p&gt;Acceptable?&lt;/p&gt;

&lt;p&gt;Probably not.&lt;/p&gt;

&lt;p&gt;This is why performance is another dimension of testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Load Testing
&lt;/h3&gt;

&lt;p&gt;Load testing checks how the system behaves under expected traffic.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1,000 concurrent users
5,000 requests/minute
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Questions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What's the response time?

What's the throughput?

How many requests fail?

How much CPU is used?

How much memory?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Stress Testing
&lt;/h3&gt;

&lt;p&gt;Stress testing goes beyond normal capacity.&lt;/p&gt;

&lt;p&gt;Maybe expected load is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;5,000 users
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We push:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10,000

20,000

50,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Where does the system break?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And equally important:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How does it break?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Does it degrade gracefully?&lt;/p&gt;

&lt;p&gt;Or completely collapse?&lt;/p&gt;

&lt;h3&gt;
  
  
  Spike Testing
&lt;/h3&gt;

&lt;p&gt;What if traffic changes like this?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1,000 users

↓

1,200

↓

1,500

↓

50,000

↓

2,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can happen from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Product launches
Breaking news
Ticket sales
Viral content
Flash sales
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spike testing checks whether infrastructure can survive sudden bursts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Soak Testing
&lt;/h3&gt;

&lt;p&gt;Some bugs don't appear immediately.&lt;/p&gt;

&lt;p&gt;A service might run beautifully for 10 minutes.&lt;/p&gt;

&lt;p&gt;After eight hours:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Memory climbs continuously.

Connections don't close.

Threads accumulate.

Disk usage increases.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Soak testing runs the system for an extended period to discover issues such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Memory leaks

Resource leaks

Connection leaks

Slow degradation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Performance Metrics That Actually Matter
&lt;/h3&gt;

&lt;p&gt;Instead of only looking at averages, modern systems often monitor percentiles.&lt;/p&gt;

&lt;p&gt;Imagine response times:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;p50 = 100 ms

p95 = 250 ms

p99 = 2,800 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The average might look fine.&lt;/p&gt;

&lt;p&gt;But 1% of users are experiencing nearly three seconds of latency.&lt;/p&gt;

&lt;p&gt;At millions of requests, that's not a small group.&lt;/p&gt;




&lt;h2&gt;
  
  
  Security Testing
&lt;/h2&gt;

&lt;p&gt;Now imagine your application is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fast ✅

Reliable ✅

Scalable ✅

Well tested ✅

Easy to use ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but this works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="s1"&gt;' OR '&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;'='&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not good.&lt;/p&gt;

&lt;p&gt;Security testing asks different questions.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Will users be able to use this?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;we also ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How could an attacker abuse this?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Testing areas include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SQL Injection

XSS

CSRF

Authentication

Authorization

Session management

Input validation

Sensitive data exposure

Security headers

HTTPS/TLS

Dependency vulnerabilities
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Authentication Is Not Authorization
&lt;/h3&gt;

&lt;p&gt;This distinction is especially important.&lt;/p&gt;

&lt;p&gt;Authentication:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Who are you?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Authorization:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What are you allowed to do?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Imagine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /api/users/100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The user is authenticated.&lt;/p&gt;

&lt;p&gt;But what happens if they change the URL?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /api/users/101
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If they can suddenly see another user's private data, authentication worked.&lt;/p&gt;

&lt;p&gt;Authorization failed.&lt;/p&gt;

&lt;p&gt;A good test suite should check both.&lt;/p&gt;




&lt;h2&gt;
  
  
  Test Coverage Is Not Test Quality
&lt;/h2&gt;

&lt;p&gt;This is another area where metrics can create false confidence.&lt;/p&gt;

&lt;p&gt;Suppose we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isAdult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;25 is an adult&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isAdult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function may have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;100% line coverage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we never tested:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;17

18

Negative values

Null

Strings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Coverage tells us:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which code executed?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It does not automatically tell us:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Did we verify the correct behavior?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Common coverage types include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Line coverage

Statement coverage

Branch coverage

Function coverage

Condition coverage

Path coverage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Branch coverage can be more useful than simple line coverage.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isAdmin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;showAdminPanel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;showDashboard&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A test that only covers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;isAdmin = true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;may execute most of the code while completely ignoring the other behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mutation Testing: An Interesting Question
&lt;/h3&gt;

&lt;p&gt;Here's a cool idea.&lt;/p&gt;

&lt;p&gt;Instead of asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How much code did my tests execute?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mutation testing asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Would my tests notice if my code were wrong?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Suppose your code says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A mutation testing tool might temporarily change it to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run your tests.&lt;/p&gt;

&lt;p&gt;If every test still passes...&lt;/p&gt;

&lt;p&gt;your tests probably missed the boundary.&lt;/p&gt;

&lt;p&gt;That's a much more interesting signal than line coverage alone.&lt;/p&gt;

&lt;p&gt;Common mutation testing tools include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PIT
Stryker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These tools help evaluate whether your tests can actually detect small changes in behavior.&lt;/p&gt;




&lt;h2&gt;
  
  
  Test Data Matters More Than It Looks
&lt;/h2&gt;

&lt;p&gt;Tests are only as useful as the situations they represent.&lt;/p&gt;

&lt;p&gt;Imagine testing a username field using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dhruv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Good start.&lt;/p&gt;

&lt;p&gt;But what about:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;D

Dhruv Patel

O'Connor

José

李明

😀

""

10,000 characters
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real users produce messy data.&lt;/p&gt;

&lt;p&gt;Test data strategies include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hardcoded data

Factories

Builders

Fixtures

Seed data

Random data

Generated data

Anonymized production data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But random data creates another problem:&lt;/p&gt;

&lt;p&gt;How do you reproduce the failure?&lt;/p&gt;

&lt;p&gt;This is why deterministic testing often matters.&lt;/p&gt;

&lt;p&gt;If random values are used, keeping a reproducible seed can help.&lt;/p&gt;




&lt;h2&gt;
  
  
  Flaky Tests Are Dangerous
&lt;/h2&gt;

&lt;p&gt;Consider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Run 1 → Pass

Run 2 → Pass

Run 3 → Fail

Run 4 → Pass

Run 5 → Fail
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No code changed.&lt;/p&gt;

&lt;p&gt;That is a flaky test.&lt;/p&gt;

&lt;p&gt;Potential causes include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Timing

Race conditions

Network dependency

Random data

Shared test state

Async behavior

Incorrect waits

External APIs

Environment differences
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Flaky tests are especially harmful because they destroy trust.&lt;/p&gt;

&lt;p&gt;Eventually a developer sees:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CI FAILED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and thinks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Probably just the flaky test again.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then one day the failure is real.&lt;/p&gt;

&lt;p&gt;And everyone ignores it.&lt;/p&gt;

&lt;p&gt;A test suite only protects the system if engineers trust it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tests Should Be Independent
&lt;/h2&gt;

&lt;p&gt;Bad:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Test A creates user

↓

Test B expects that user

↓

Test C deletes that user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Test B runs first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FAIL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Test C runs before B:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FAIL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tests shouldn't depend on execution order.&lt;/p&gt;

&lt;p&gt;Each test should ideally create the state it needs and clean up afterward.&lt;/p&gt;




&lt;h2&gt;
  
  
  Test Behavior, Not Implementation Details
&lt;/h2&gt;

&lt;p&gt;Suppose we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getFullName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A good test asks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Does getFullName return "Dhruv Patel"?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A fragile test might assert internal calls that aren't actually part of the requirement.&lt;/p&gt;

&lt;p&gt;Why is that bad?&lt;/p&gt;

&lt;p&gt;Because now harmless refactoring breaks tests.&lt;/p&gt;

&lt;p&gt;Tests should ideally survive implementation changes as long as externally expected behavior remains correct.&lt;/p&gt;

&lt;p&gt;That leads to an excellent principle:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tests should make refactoring safer, not punish you for refactoring.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Avoid Logic Inside Tests
&lt;/h2&gt;

&lt;p&gt;Tests should be boring.&lt;/p&gt;

&lt;p&gt;That is a compliment.&lt;/p&gt;

&lt;p&gt;Bad:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// calculate expected result dynamically&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your test itself contains business logic.&lt;/p&gt;

&lt;p&gt;Which raises an uncomfortable question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Who tests the test?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Usually, explicit expected values are easier to reason about.&lt;/p&gt;




&lt;h2&gt;
  
  
  One Test, One Reason to Fail
&lt;/h2&gt;

&lt;p&gt;Imagine a single test checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User creation
Email delivery
Database persistence
Analytics event
Notification
Profile generation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It fails.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Good luck.&lt;/p&gt;

&lt;p&gt;Tests should usually be focused enough that a failure tells you something useful immediately.&lt;/p&gt;

&lt;p&gt;A good test name might be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rejects checkout when inventory is unavailable&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;works&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One of those helps at 2 AM.&lt;/p&gt;

&lt;p&gt;The other becomes a personal attack.&lt;/p&gt;




&lt;h2&gt;
  
  
  CI Turns Tests Into a Safety System
&lt;/h2&gt;

&lt;p&gt;Tests sitting on a developer's laptop aren't enough.&lt;/p&gt;

&lt;p&gt;Modern teams connect tests to Continuous Integration.&lt;/p&gt;

&lt;p&gt;A typical pipeline might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Developer pushes code
        ↓
Lint
        ↓
Unit Tests
        ↓
Integration Tests
        ↓
Coverage
        ↓
Security Checks
        ↓
Build
        ↓
E2E Tests
        ↓
Deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A pull request might require:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unit tests ✅

Integration tests ✅

Coverage threshold ✅

Static analysis ✅

Security scan ✅

Build ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;before merging.&lt;/p&gt;

&lt;p&gt;This turns testing from:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Something developers should remember to do.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;into:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Something the engineering system automatically enforces.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Why Fast Feedback Matters
&lt;/h3&gt;

&lt;p&gt;Imagine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unit tests → 20 seconds

Integration → 4 minutes

E2E → 25 minutes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running everything sequentially before showing any result would be frustrating.&lt;/p&gt;

&lt;p&gt;Instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fast tests first
       ↓
Cheap failures detected quickly
       ↓
Expensive tests later
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no reason to spend 25 minutes running E2E tests if:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;calculateTax()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;already fails a unit test after seven seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing Microservices Is Harder
&lt;/h2&gt;

&lt;p&gt;Now replace one application with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Frontend

↓

API Gateway

↓

User Service

Order Service

Payment Service

Inventory Service

Notification Service

Analytics Service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suddenly testing becomes distributed.&lt;/p&gt;

&lt;p&gt;Questions appear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What if Payment Service is down?

What if Inventory Service is slow?

What if Order Service retries the same request?

What if an event arrives twice?

What if an event arrives out of order?

What if two services use incompatible API versions?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Integration testing

Contract testing

API testing

Event testing

Resilience testing

Observability
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;become increasingly important.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contract Testing
&lt;/h3&gt;

&lt;p&gt;Imagine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Order Service
     ↓
Payment Service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Order Service expects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Payment Service changes its response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"paymentStatus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both services may pass their own unit tests.&lt;/p&gt;

&lt;p&gt;Production still breaks.&lt;/p&gt;

&lt;p&gt;Contract testing checks whether interacting services continue to agree on their interface.&lt;/p&gt;

&lt;p&gt;Tools like Pact exist for this type of problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing Non-Functional Requirements
&lt;/h2&gt;

&lt;p&gt;Testing isn't limited to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Button works.

API returns result.

Database saves record.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Production systems also have requirements like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;99.9% availability

Handles 10,000 users

Recovers after node failure

Backups restore successfully

Continues operating with degraded services
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So your testing strategy may also need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Reliability testing

Availability testing

Scalability testing

Resilience testing

Failover testing

Disaster recovery testing

Backup/restore testing

Network failure simulation

Latency injection

Load-shedding testing

Graceful degradation verification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What Happens If Redis Dies?
&lt;/h3&gt;

&lt;p&gt;This is a much more useful testing question than:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is Redis connected?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Suppose Redis handles caching.&lt;/p&gt;

&lt;p&gt;Redis fails.&lt;/p&gt;

&lt;p&gt;Does the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Crash completely?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fall back to the database?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maybe performance becomes slower, but the core experience continues.&lt;/p&gt;

&lt;p&gt;That is graceful degradation.&lt;/p&gt;

&lt;p&gt;Testing real systems increasingly means testing failures intentionally.&lt;/p&gt;

&lt;h3&gt;
  
  
  What If the Network Becomes Slow?
&lt;/h3&gt;

&lt;p&gt;Distributed applications depend on networks.&lt;/p&gt;

&lt;p&gt;Networks fail.&lt;/p&gt;

&lt;p&gt;Requests can:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Time out

Arrive late

Be duplicated

Be dropped

Arrive out of order
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So mature testing strategies don't only test perfect networks.&lt;/p&gt;

&lt;p&gt;They deliberately simulate bad ones.&lt;/p&gt;

&lt;p&gt;This is a major shift in mindset:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Don't only test the system in the environment you hope exists.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Test the environment that eventually will exist.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Testing Ice Cream Cone Anti-Pattern
&lt;/h2&gt;

&lt;p&gt;Imagine a test suite with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Very few unit tests

Some integration tests

Huge number of E2E/manual tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's sometimes described as an ice cream cone.&lt;/p&gt;

&lt;p&gt;Why is it problematic?&lt;/p&gt;

&lt;p&gt;Because most of the confidence depends on expensive, slow tests.&lt;/p&gt;

&lt;p&gt;You might end up with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2-hour pipelines

Flaky browsers

Hard-to-debug failures

High maintenance cost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A balanced test strategy tries to catch defects as cheaply as practical.&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing Legacy Code
&lt;/h2&gt;

&lt;p&gt;Now imagine joining a codebase with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;500,000 lines of code

Almost no tests

Business-critical behavior

Very little documentation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Should you rewrite everything?&lt;/p&gt;

&lt;p&gt;Probably not.&lt;/p&gt;

&lt;p&gt;One useful approach is characterization testing.&lt;/p&gt;

&lt;p&gt;Instead of initially asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What should this code do?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;you capture:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What does this code currently do?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then tests protect existing behavior while you gradually improve the system.&lt;/p&gt;

&lt;p&gt;This can give you enough safety to refactor without accidentally destroying undocumented business logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  Debugging a Failing Test
&lt;/h2&gt;

&lt;p&gt;When a test fails, avoid immediately changing the assertion just to make it green.&lt;/p&gt;

&lt;p&gt;Investigate.&lt;/p&gt;

&lt;p&gt;A useful flow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read failure message

↓

Check stack trace

↓

Run failing test alone

↓

Reproduce consistently

↓

Inspect test data

↓

Inspect mocks

↓

Check environment

↓

Debug application logic

↓

Find root cause
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Common tricky cases include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Local passes → CI fails

Individual test passes → suite fails

Fails only at midnight

Fails only in a different timezone

Fails only under parallel execution

Fails because a previous test polluted state
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  AI and the Future of Software Testing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  And Then AI Entered the Room
&lt;/h3&gt;

&lt;p&gt;This is where software testing becomes especially interesting in 2026.&lt;/p&gt;

&lt;p&gt;AI can generate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Functions

APIs

Database queries

Components

Unit tests

Mocks

Fixtures

E2E scripts

Documentation

Refactors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this is incredibly useful.&lt;/p&gt;

&lt;p&gt;You can ask an AI coding tool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Generate boundary tests for this validator.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and get useful scenarios in seconds.&lt;/p&gt;

&lt;p&gt;Or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Write Playwright tests for this checkout flow.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Identify edge cases in this API.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AI can dramatically reduce the mechanical work involved in testing.&lt;/p&gt;

&lt;p&gt;But there is one subtle problem.&lt;/p&gt;

&lt;p&gt;Imagine AI writes this requirement incorrectly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Users under 18 cannot register.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The real requirement was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Users under 16 cannot register.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AI writes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Too young&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then AI generates tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toThrow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toThrow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PASS ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Coverage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;100% ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Code review:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Looks clean ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Requirement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WRONG ❌
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the scary part.&lt;/p&gt;

&lt;p&gt;The implementation and the tests can agree perfectly...&lt;/p&gt;

&lt;p&gt;and both be wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Can Automate Tests. It Cannot Define Intent for Us
&lt;/h3&gt;

&lt;p&gt;This is the distinction I keep coming back to.&lt;/p&gt;

&lt;p&gt;AI is very good at asking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What tests could be written for this implementation?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Engineers still need to ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Is this implementation solving the right problem?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's why AI-generated tests still need human review.&lt;/p&gt;

&lt;p&gt;Questions worth asking include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Does this test reflect a real requirement?

Did AI copy implementation assumptions into the test?

Are edge cases missing?

Are mocks realistic?

Does this test challenge the code?

Or is the test merely confirming what the code already assumes?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The biggest danger may not be AI writing obviously broken tests.&lt;/p&gt;

&lt;p&gt;Those are easy to catch.&lt;/p&gt;

&lt;p&gt;The bigger danger is AI writing tests that look extremely convincing.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Better Mental Model for AI-Assisted Testing
&lt;/h3&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI writes code
      ↓
AI writes tests
      ↓
Tests pass
      ↓
Ship
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I prefer thinking about it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Requirements
      ↓
AI generates implementation
      ↓
AI helps generate tests
      ↓
Human validates intent
      ↓
Tests challenge assumptions
      ↓
CI enforces rules
      ↓
Production provides feedback
      ↓
Regression tests capture failures
      ↓
System improves
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AI can accelerate almost every step.&lt;/p&gt;

&lt;p&gt;But acceleration isn't the same as correctness.&lt;/p&gt;




&lt;h2&gt;
  
  
  Production Is the Final Reality Check
&lt;/h2&gt;

&lt;p&gt;You can simulate a lot.&lt;/p&gt;

&lt;p&gt;But production will always introduce situations you did not expect.&lt;/p&gt;

&lt;p&gt;Maybe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A customer uploads a 600 MB image.

An API suddenly responds slowly.

Traffic jumps 40x.

A database replica falls behind.

Users discover a strange workflow.

An external dependency changes behavior.

A race condition appears once every 50,000 requests.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is why testing connects naturally to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Monitoring

Logging

Tracing

Metrics

Error tracking

Incident response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Production feedback should feed back into your test suite.&lt;/p&gt;

&lt;p&gt;That creates a loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Build

↓

Test

↓

Deploy

↓

Observe

↓

Learn

↓

Add regression test

↓

Improve

↓

Repeat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  My Testing Mental Model
&lt;/h2&gt;

&lt;p&gt;After going through all of these concepts, this is the simplest model I've found useful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Requirements
      ↓
Understand expected behavior
      ↓
Identify risks
      ↓
Unit tests
      ↓
Integration tests
      ↓
API / contract tests
      ↓
Critical E2E tests
      ↓
Performance tests
      ↓
Security tests
      ↓
CI enforcement
      ↓
Production monitoring
      ↓
Regression tests
      ↓
Repeat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not every application needs every testing technique.&lt;/p&gt;

&lt;p&gt;A small portfolio site doesn't need the testing infrastructure of Netflix.&lt;/p&gt;

&lt;p&gt;A banking system shouldn't use the testing strategy of a weekend todo app.&lt;/p&gt;

&lt;p&gt;Testing is an engineering tradeoff.&lt;/p&gt;

&lt;p&gt;You balance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Confidence

Speed

Risk

Complexity

Cost

Maintenance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What Should Developers Actually Know for Interviews?
&lt;/h2&gt;

&lt;p&gt;You probably don't need to memorize every testing framework ever created.&lt;/p&gt;

&lt;p&gt;But you should be able to explain the reasoning.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;h3&gt;
  
  
  What Is the Testing Pyramid?
&lt;/h3&gt;

&lt;p&gt;Explain why we typically have many unit tests, fewer integration tests, and fewer E2E tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mock vs Stub?
&lt;/h3&gt;

&lt;p&gt;Explain their purpose and when you'd prefer real dependencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Would You Test a REST API?
&lt;/h3&gt;

&lt;p&gt;Talk about:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Success cases

Validation

Authentication

Authorization

Errors

Boundaries

Database state

Rate limits

Contracts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How Would You Test a Login System?
&lt;/h3&gt;

&lt;p&gt;Don't just say:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Correct username/password.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think about:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Wrong password

Missing fields

Locked user

Expired token

Brute-force protection

Rate limiting

Session expiration

Authorization

Concurrent sessions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How Do You Handle Flaky Tests?
&lt;/h3&gt;

&lt;p&gt;Discuss:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Reproduction

Isolation

Timing

Shared state

Network dependencies

Correct waits

Fixing rather than permanently ignoring them
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What's a Good Coverage Percentage?
&lt;/h3&gt;

&lt;p&gt;The strongest answer usually isn't:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;100%.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Coverage is useful as a signal, but meaningful behavioral coverage and risk coverage matter more than chasing a percentage.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Biggest Lesson I Learned
&lt;/h2&gt;

&lt;p&gt;Before studying testing deeply, I thought:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Testing = Write tests until they're green.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I think:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Testing = Build evidence that the system behaves correctly under conditions that matter.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is a very different mindset.&lt;/p&gt;

&lt;p&gt;And maybe the biggest shift is this:&lt;/p&gt;

&lt;p&gt;Don't ask only:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does my code work?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When doesn't it work?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What assumption am I making?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What happens at the boundary?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What happens when the dependency fails?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What happens when two things happen at once?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What happens when someone intentionally abuses this?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What happens when traffic is 100x larger?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does this test verify the requirement, or merely repeat the implementation?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those questions are where testing starts becoming engineering.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Software testing isn't about writing hundreds of &lt;code&gt;expect()&lt;/code&gt; statements.&lt;/p&gt;

&lt;p&gt;It's about confidence.&lt;/p&gt;

&lt;p&gt;Not fake confidence from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tests: 2,421 passed ✅
Coverage: 98% ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but meaningful confidence that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Users can complete critical workflows.

Invalid inputs are rejected.

Services communicate correctly.

Failures are handled safely.

Security boundaries hold.

Performance remains acceptable.

Old bugs don't return.

New changes don't silently break existing behavior.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AI will probably make writing tests dramatically easier.&lt;/p&gt;

&lt;p&gt;It will generate unit tests.&lt;/p&gt;

&lt;p&gt;Suggest edge cases.&lt;/p&gt;

&lt;p&gt;Build fixtures.&lt;/p&gt;

&lt;p&gt;Create mocks.&lt;/p&gt;

&lt;p&gt;Write Playwright flows.&lt;/p&gt;

&lt;p&gt;Analyze failures.&lt;/p&gt;

&lt;p&gt;Maybe even automatically repair some broken tests.&lt;/p&gt;

&lt;p&gt;But that makes engineering judgment more important, not less.&lt;/p&gt;

&lt;p&gt;Because if software can be generated faster than humans can manually inspect it, our ability to verify behavior becomes one of the most important parts of software development.&lt;/p&gt;

&lt;p&gt;The future might not simply be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AI writes more code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It might be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Engineers become much better at proving whether generated code deserves to be trusted.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And perhaps that's the real purpose of testing.&lt;/p&gt;

&lt;p&gt;Not proving perfection.&lt;/p&gt;

&lt;p&gt;Building enough evidence to confidently ship something into an imperfect world.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Testing Cheat Sheet
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unit Testing
→ Does this individual piece work?

Integration Testing
→ Do these pieces work together?

API Testing
→ Does the interface behave correctly?

E2E Testing
→ Can the user complete the journey?

Regression Testing
→ Did new code break old behavior?

Performance Testing
→ Does it still work under pressure?

Security Testing
→ Can someone misuse or exploit it?

Smoke Testing
→ Is the build basically alive?

TDD
→ Test → Implement → Refactor

BDD
→ Given → When → Then

Coverage
→ What code did our tests execute?

Mutation Testing
→ Would our tests detect incorrect code?

CI Testing
→ Automatically protect every change.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the simplest rule I want to remember:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Don't write tests just to make the test suite green. Write tests that would actually scare you if they failed.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Keep Learning
&lt;/h2&gt;

&lt;p&gt;If you're learning software engineering too, I hope this gives you a clearer mental model of where testing fits into the bigger picture.&lt;/p&gt;

&lt;p&gt;I'm continuing to dive deeper into testing, debugging, system design, distributed systems, and the engineering concepts that sit underneath the frameworks we use every day.&lt;/p&gt;

&lt;p&gt;If you found this useful, drop a comment:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the hardest bug you've encountered that somehow survived the test suite?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'd genuinely love to hear the stories. 👀&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>testing</category>
      <category>software</category>
    </item>
    <item>
      <title>System Design Fundamentals</title>
      <dc:creator>Dhruv Patel</dc:creator>
      <pubDate>Sat, 08 Aug 2026 18:25:26 +0000</pubDate>
      <link>https://dev.to/dhruvtechdev/system-design-fundamentals-55pn</link>
      <guid>https://dev.to/dhruvtechdev/system-design-fundamentals-55pn</guid>
      <description>&lt;p&gt;System Design is the process of planning how a software system should work before building it.&lt;/p&gt;

&lt;p&gt;Think about constructing a large building. Before workers start putting up walls, architects decide where the rooms, elevators, electricity, water systems, emergency exits, and entrances should go.&lt;/p&gt;

&lt;p&gt;Software works in a similar way.&lt;/p&gt;

&lt;p&gt;When developers build applications such as Amazon, Instagram, Netflix, Uber, or WhatsApp, they cannot simply start writing code and hope everything works. They first need to decide how millions of users, servers, databases, files, and requests will work together.&lt;/p&gt;

&lt;p&gt;A simple way to remember it is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;System Design = The blueprint of a software system.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What Do We Decide in System Design?
&lt;/h2&gt;

&lt;p&gt;During system design, engineers make decisions about things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How users connect to the application&lt;/li&gt;
&lt;li&gt;Where information is stored&lt;/li&gt;
&lt;li&gt;How different parts of the application communicate&lt;/li&gt;
&lt;li&gt;How images and videos are stored&lt;/li&gt;
&lt;li&gt;How the system handles millions of users&lt;/li&gt;
&lt;li&gt;How the application stays fast&lt;/li&gt;
&lt;li&gt;How failures are handled&lt;/li&gt;
&lt;li&gt;How user information stays secure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, imagine designing WhatsApp.&lt;/p&gt;

&lt;p&gt;A user sends a message. That message must travel to WhatsApp's servers, reach the correct person, possibly be stored temporarily, appear on multiple devices, and trigger a notification.&lt;/p&gt;

&lt;p&gt;If millions of people send messages at the same time, the system must continue working without becoming extremely slow or crashing.&lt;/p&gt;

&lt;p&gt;That planning is system design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does System Design Matter?
&lt;/h2&gt;

&lt;p&gt;A good software system should be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast&lt;/li&gt;
&lt;li&gt;Reliable&lt;/li&gt;
&lt;li&gt;Secure&lt;/li&gt;
&lt;li&gt;Scalable&lt;/li&gt;
&lt;li&gt;Affordable to operate&lt;/li&gt;
&lt;li&gt;Easy to maintain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Imagine Instagram without good system design.&lt;/p&gt;

&lt;p&gt;Millions of users might open the application at the same time. Servers could become overloaded, photos might take several seconds to load, comments could disappear, and the application might frequently crash.&lt;/p&gt;

&lt;p&gt;System design helps engineers prepare for these situations before they become major problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  System Design in Software Interviews
&lt;/h2&gt;

&lt;p&gt;System design is also common in software engineering interviews.&lt;/p&gt;

&lt;p&gt;An interviewer may ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Design YouTube&lt;/li&gt;
&lt;li&gt;Design Uber&lt;/li&gt;
&lt;li&gt;Design Twitter&lt;/li&gt;
&lt;li&gt;Design WhatsApp&lt;/li&gt;
&lt;li&gt;Design a URL Shortener&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interviewer normally does not expect one perfect answer.&lt;/p&gt;

&lt;p&gt;Instead, they want to understand how you think.&lt;/p&gt;

&lt;p&gt;They are looking at whether you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand the problem&lt;/li&gt;
&lt;li&gt;Ask useful questions&lt;/li&gt;
&lt;li&gt;Estimate the size of the system&lt;/li&gt;
&lt;li&gt;Choose appropriate technologies&lt;/li&gt;
&lt;li&gt;Identify possible problems&lt;/li&gt;
&lt;li&gt;Explain advantages and disadvantages&lt;/li&gt;
&lt;li&gt;Improve the design when requirements change&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;System design is therefore less about memorizing architectures and more about learning how to make engineering decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  High-Level Design and Low-Level Design
&lt;/h2&gt;

&lt;p&gt;System design can be viewed at two different levels.&lt;/p&gt;

&lt;h3&gt;
  
  
  High-Level Design
&lt;/h3&gt;

&lt;p&gt;High-Level Design, or HLD, focuses on the big picture.&lt;/p&gt;

&lt;p&gt;For example, an application's architecture might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
 ↓
Load Balancer
 ↓
Application Servers
 ↓
Database
 ↓
Cache
 ↓
File Storage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this level, engineers think about major components such as servers, databases, storage, APIs, and caching.&lt;/p&gt;

&lt;p&gt;Think of HLD as looking at the map of an entire city.&lt;/p&gt;

&lt;h3&gt;
  
  
  Low-Level Design
&lt;/h3&gt;

&lt;p&gt;Low-Level Design, or LLD, focuses on smaller implementation details.&lt;/p&gt;

&lt;p&gt;For example, while building a shopping cart, developers may design:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cart

addItem()

removeItem()

calculateTotal()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here the focus is on classes, methods, objects, database structures, and design patterns.&lt;/p&gt;

&lt;p&gt;A simple memory trick is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;HLD = City map&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LLD = House blueprint&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Functional Requirements
&lt;/h2&gt;

&lt;p&gt;Functional requirements describe what the application should do.&lt;/p&gt;

&lt;p&gt;For WhatsApp, examples could be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send messages&lt;/li&gt;
&lt;li&gt;Receive messages&lt;/li&gt;
&lt;li&gt;Create groups&lt;/li&gt;
&lt;li&gt;Share photos&lt;/li&gt;
&lt;li&gt;Delete messages&lt;/li&gt;
&lt;li&gt;Make calls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the actual features users interact with.&lt;/p&gt;

&lt;p&gt;Think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Functional requirement = What should the system do?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Non-Functional Requirements
&lt;/h2&gt;

&lt;p&gt;Non-functional requirements describe how well those features should work.&lt;/p&gt;

&lt;p&gt;For example, sending a message is a functional requirement.&lt;/p&gt;

&lt;p&gt;But we may also say:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The message should arrive within one second.&lt;/li&gt;
&lt;li&gt;The service should almost always be available.&lt;/li&gt;
&lt;li&gt;Messages should be encrypted.&lt;/li&gt;
&lt;li&gt;The system should support millions of users.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These describe the quality of the system.&lt;/p&gt;

&lt;p&gt;Think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Functional = What it does&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Non-functional = How well it does it&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Estimating the Size of the System
&lt;/h2&gt;

&lt;p&gt;Before designing a large system, engineers usually make rough calculations.&lt;/p&gt;

&lt;p&gt;This is called &lt;strong&gt;back-of-the-envelope estimation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The goal is not perfect mathematics. The goal is understanding approximately how large the system might become.&lt;/p&gt;

&lt;p&gt;Suppose one million users each upload one 5 MB photo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1,000,000 × 5 MB
= approximately 5 TB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we know the system may need several terabytes of storage.&lt;/p&gt;

&lt;p&gt;Four common estimates are especially useful.&lt;/p&gt;

&lt;h3&gt;
  
  
  DAU
&lt;/h3&gt;

&lt;p&gt;DAU means &lt;strong&gt;Daily Active Users&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It tells us how many people use the application each day.&lt;/p&gt;

&lt;p&gt;If an application has 10 million registered users but only 2 million use it today:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DAU = 2 million
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  QPS
&lt;/h3&gt;

&lt;p&gt;QPS means &lt;strong&gt;Queries or Requests Per Second&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It tells us how many requests the system receives every second.&lt;/p&gt;

&lt;p&gt;If a website receives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;864,000 requests per day
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then approximately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;864,000 ÷ 86,400 seconds
= 10 requests per second
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;QPS = 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Storage
&lt;/h3&gt;

&lt;p&gt;Storage tells us how much information must be saved.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;100 million photos
×
3 MB each
=
approximately 300 TB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bandwidth
&lt;/h3&gt;

&lt;p&gt;Bandwidth represents how much information moves through the network.&lt;/p&gt;

&lt;p&gt;For example, if 1,000 people download a 5 MB image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1,000 × 5 MB
= 5,000 MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A simple memory trick is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DAU       → Users
QPS       → Requests
Storage   → Saved data
Bandwidth → Moving data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Read-Heavy and Write-Heavy Systems
&lt;/h2&gt;

&lt;p&gt;Applications constantly read and write information.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;read&lt;/strong&gt; means getting existing information.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Watching a YouTube video&lt;/li&gt;
&lt;li&gt;Reading a news article&lt;/li&gt;
&lt;li&gt;Viewing an Instagram post&lt;/li&gt;
&lt;li&gt;Searching Google&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A &lt;strong&gt;write&lt;/strong&gt; means creating or changing information.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sending a message&lt;/li&gt;
&lt;li&gt;Uploading a photo&lt;/li&gt;
&lt;li&gt;Creating an order&lt;/li&gt;
&lt;li&gt;Updating a bank transaction&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some applications are mostly read-heavy.&lt;/p&gt;

&lt;p&gt;Instagram, for example, has huge numbers of people viewing posts while a smaller percentage are uploading content.&lt;/p&gt;

&lt;p&gt;Other applications can have large amounts of writing.&lt;/p&gt;

&lt;p&gt;Messaging systems receive new messages constantly.&lt;/p&gt;

&lt;p&gt;Understanding whether a system performs more reads or writes helps engineers choose the right architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Latency and Throughput
&lt;/h2&gt;

&lt;p&gt;These two concepts describe system performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Latency
&lt;/h3&gt;

&lt;p&gt;Latency means how long one operation takes.&lt;/p&gt;

&lt;p&gt;If you press the login button and the result appears after 100 milliseconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Latency = 100 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lower latency usually means the application feels faster.&lt;/p&gt;

&lt;h3&gt;
  
  
  Throughput
&lt;/h3&gt;

&lt;p&gt;Throughput means how much work the system can handle within a period of time.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10,000 requests per second
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is a measure of throughput.&lt;/p&gt;

&lt;p&gt;Think:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Latency    → How fast one request finishes
Throughput → How many requests can be handled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A highway is a useful analogy.&lt;/p&gt;

&lt;p&gt;Latency is how long one car takes to reach its destination.&lt;/p&gt;

&lt;p&gt;Throughput is how many cars the highway can handle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Availability and Consistency
&lt;/h2&gt;

&lt;p&gt;Another important system design decision involves availability and consistency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Availability
&lt;/h3&gt;

&lt;p&gt;Availability means the system continues responding when users need it.&lt;/p&gt;

&lt;p&gt;For something like a social media feed, displaying information that is a few seconds old may sometimes be acceptable if the application keeps working.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consistency
&lt;/h3&gt;

&lt;p&gt;Consistency means users receive the correct and expected version of the information.&lt;/p&gt;

&lt;p&gt;Consider a bank account.&lt;/p&gt;

&lt;p&gt;If you transfer $100, your balance should correctly reflect that transaction.&lt;/p&gt;

&lt;p&gt;Showing an outdated balance could cause serious problems.&lt;/p&gt;

&lt;p&gt;Therefore, banking systems often care strongly about consistency.&lt;/p&gt;

&lt;p&gt;A simple way to remember:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Availability → Keep working
Consistency  → Keep data correct
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Different applications may prioritize these differently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trade-Offs
&lt;/h2&gt;

&lt;p&gt;Trade-offs are one of the most important ideas in system design.&lt;/p&gt;

&lt;p&gt;Almost every engineering decision improves one thing while creating another cost.&lt;/p&gt;

&lt;p&gt;For example, a cache can make an application much faster.&lt;/p&gt;

&lt;p&gt;But cached information may sometimes become outdated.&lt;/p&gt;

&lt;p&gt;Database replication can improve reliability.&lt;/p&gt;

&lt;p&gt;But maintaining multiple database copies makes the system more complicated.&lt;/p&gt;

&lt;p&gt;Compression can reduce file sizes.&lt;/p&gt;

&lt;p&gt;But compressing and decompressing information requires additional processing power.&lt;/p&gt;

&lt;p&gt;There is rarely a completely free improvement.&lt;/p&gt;

&lt;p&gt;Engineers constantly ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What do we gain, and what does it cost us?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  There Is No Perfect System Design
&lt;/h2&gt;

&lt;p&gt;Different applications have different priorities.&lt;/p&gt;

&lt;p&gt;A bank may prioritize:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security&lt;/li&gt;
&lt;li&gt;Data accuracy&lt;/li&gt;
&lt;li&gt;Reliability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Netflix may prioritize:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast video delivery&lt;/li&gt;
&lt;li&gt;Availability&lt;/li&gt;
&lt;li&gt;Global performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Uber may prioritize:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time location&lt;/li&gt;
&lt;li&gt;Low latency&lt;/li&gt;
&lt;li&gt;Availability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Amazon may prioritize:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reliability&lt;/li&gt;
&lt;li&gt;Scalability&lt;/li&gt;
&lt;li&gt;Accurate transactions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because their requirements are different, their architectures will also be different.&lt;/p&gt;

&lt;p&gt;That is why there is no single perfect architecture for every application.&lt;/p&gt;

&lt;p&gt;There is only a design that best matches the requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Simple System Design Process
&lt;/h2&gt;

&lt;p&gt;When solving a system design problem, do not immediately start drawing servers and databases.&lt;/p&gt;

&lt;p&gt;Use a simple process.&lt;/p&gt;

&lt;p&gt;First, understand the requirements.&lt;/p&gt;

&lt;p&gt;Ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What exactly are we building?
What features are required?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then estimate the scale.&lt;/p&gt;

&lt;p&gt;Ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;How many users?
How many requests?
How much data?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create the basic architecture.&lt;/p&gt;

&lt;p&gt;Think about:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Users
Servers
APIs
Databases
Storage
Cache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, identify possible bottlenecks.&lt;/p&gt;

&lt;p&gt;Ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What happens if millions of users arrive?
Can the database become slow?
What happens if one server crashes?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then improve the architecture using technologies such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Load Balancers
Caching
CDNs
Database Replication
Message Queues
Additional Servers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Continue improving the design while discussing the trade-offs of each decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Mental Model
&lt;/h2&gt;

&lt;p&gt;You do not need to memorize hundreds of architectures to understand system design.&lt;/p&gt;

&lt;p&gt;Remember this flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Requirements
      ↓
Estimate Scale
      ↓
Design Architecture
      ↓
Choose Database &amp;amp; Storage
      ↓
Improve Speed with Caching
      ↓
Scale for More Users
      ↓
Find Bottlenecks
      ↓
Discuss Trade-offs
      ↓
Improve the Design
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The easiest one-line memory trick is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;System Design = Requirements → Estimate → Architecture → Database → Cache → Scale → Trade-offs → Improve&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once this thinking process becomes natural, designing systems such as Instagram, Uber, Netflix, WhatsApp, or Amazon becomes much easier because the same fundamental ideas appear again and again.&lt;/p&gt;

</description>
      <category>software</category>
      <category>programming</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>What I Learned After Building a Redis Queue Feature in SyncFlow</title>
      <dc:creator>Dhruv Patel</dc:creator>
      <pubDate>Sun, 28 Jun 2026 10:07:31 +0000</pubDate>
      <link>https://dev.to/dhruvtechdev/what-i-learned-after-building-a-redis-queue-feature-in-syncflow-c79</link>
      <guid>https://dev.to/dhruvtechdev/what-i-learned-after-building-a-redis-queue-feature-in-syncflow-c79</guid>
      <description>&lt;p&gt;While working on &lt;strong&gt;SyncFlow&lt;/strong&gt;, a Shopify embedded app, I recently completed &lt;strong&gt;US-002 — Redis Queue Foundation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The purpose of this feature was simple:&lt;/p&gt;

&lt;p&gt;Move inventory sync work away from the main request flow and process it in the background using Redis-backed queues.&lt;/p&gt;

&lt;p&gt;At first, the feature looked complete. The queue files were added, Redis configuration was created, producers and workers were implemented, retry handling was introduced, and logging was added.&lt;/p&gt;

&lt;p&gt;But after reviewing the uncommitted changes properly, I learned something important:&lt;/p&gt;

&lt;p&gt;A feature is not complete when the code is written.&lt;br&gt;
A feature is complete when it is reliable, reproducible, testable, and safe to run.&lt;/p&gt;
&lt;h2&gt;
  
  
  What the Feature Was Supposed to Do
&lt;/h2&gt;

&lt;p&gt;The goal of US-002 was to create a foundation for background job processing.&lt;/p&gt;

&lt;p&gt;The feature included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redis connection setup&lt;/li&gt;
&lt;li&gt;Queue configuration&lt;/li&gt;
&lt;li&gt;Primary sync queue&lt;/li&gt;
&lt;li&gt;Retry queue&lt;/li&gt;
&lt;li&gt;Dead-letter queue&lt;/li&gt;
&lt;li&gt;Queue producer&lt;/li&gt;
&lt;li&gt;Queue worker&lt;/li&gt;
&lt;li&gt;Queue health check&lt;/li&gt;
&lt;li&gt;Structured queue logging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The idea was to make inventory sync more reliable.&lt;/p&gt;

&lt;p&gt;Instead of blocking the app request while sync logic runs, the app can now publish a job to a queue. A worker can process that job separately. If the job fails, it can be retried. If it keeps failing, it can move to a dead-letter queue.&lt;/p&gt;

&lt;p&gt;That sounds good in theory.&lt;/p&gt;

&lt;p&gt;But the review showed that implementation details matter a lot.&lt;/p&gt;
&lt;h2&gt;
  
  
  Lesson 1: TypeScript Errors Can Block the Entire Feature
&lt;/h2&gt;

&lt;p&gt;One of the first issues found was a TypeScript syntax error in the queue health file.&lt;/p&gt;

&lt;p&gt;Because of that, &lt;code&gt;npm run typecheck&lt;/code&gt; failed before the app could build.&lt;/p&gt;

&lt;p&gt;This was a clear reminder that type checking is not optional in a TypeScript project.&lt;/p&gt;

&lt;p&gt;Even if the logic looks correct, invalid types can stop the whole application from being production-ready.&lt;/p&gt;

&lt;p&gt;Before committing a feature, I should always run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run typecheck
npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For backend-heavy features, I should also run the worker process locally and confirm that the app and worker can both start correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 2: Dependency Management Must Be Reproducible
&lt;/h2&gt;

&lt;p&gt;The feature added new packages like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bullmq&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ioredis&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pino&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tsx&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the lockfile was not updated correctly.&lt;/p&gt;

&lt;p&gt;There was also an untracked &lt;code&gt;pnpm-lock.yaml&lt;/code&gt;, while the project was using &lt;code&gt;package-lock.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This creates a serious problem.&lt;/p&gt;

&lt;p&gt;If another developer pulls the repo, installs dependencies, and runs the project, their environment may not match mine.&lt;/p&gt;

&lt;p&gt;The lesson is simple:&lt;/p&gt;

&lt;p&gt;Pick one package manager and stay consistent.&lt;/p&gt;

&lt;p&gt;For example, if the project uses npm, commit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;package.json
package-lock.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And remove accidental lockfiles like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm-lock.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A feature is not reproducible if dependencies are not locked correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 3: Health Endpoints Should Report Failure, Not Crash
&lt;/h2&gt;

&lt;p&gt;A health endpoint should help debug the system.&lt;/p&gt;

&lt;p&gt;It should not become another reason the app crashes.&lt;/p&gt;

&lt;p&gt;In this feature, the health route had two problems.&lt;/p&gt;

&lt;p&gt;First, it imported from a package that was not declared in the project. Second, the Redis connection code could throw immediately if &lt;code&gt;REDIS_URL&lt;/code&gt; was missing.&lt;/p&gt;

&lt;p&gt;That means the health endpoint might crash instead of returning a clean unhealthy response.&lt;/p&gt;

&lt;p&gt;A better health endpoint should return something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"unhealthy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"redis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"missing_config"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"worker"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"not_ready"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With an HTTP status like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;503 Service Unavailable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lesson:&lt;/p&gt;

&lt;p&gt;Health checks should be defensive. Their job is to explain what is broken, not fail silently or crash the route.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 4: Every Queue Needs a Consumer
&lt;/h2&gt;

&lt;p&gt;The retry queue was created, and jobs could be added to it.&lt;/p&gt;

&lt;p&gt;But only the main sync queue had a worker.&lt;/p&gt;

&lt;p&gt;That means retry jobs could sit inside the retry queue forever.&lt;/p&gt;

&lt;p&gt;This is a common design mistake in queue-based systems.&lt;/p&gt;

&lt;p&gt;Creating a queue is not enough.&lt;/p&gt;

&lt;p&gt;Every queue must have a clear data flow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who writes to it?&lt;/li&gt;
&lt;li&gt;Who reads from it?&lt;/li&gt;
&lt;li&gt;When does the job move?&lt;/li&gt;
&lt;li&gt;What happens if it fails?&lt;/li&gt;
&lt;li&gt;What happens after max retries?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a retry queue, there are usually two options.&lt;/p&gt;

&lt;p&gt;One option is to use the queue system’s built-in retry mechanism.&lt;/p&gt;

&lt;p&gt;Another option is to create a separate retry worker that moves jobs back to the main queue after a delay.&lt;/p&gt;

&lt;p&gt;Without that, retry logic only exists on paper.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 5: Job Types Should Be Strict
&lt;/h2&gt;

&lt;p&gt;The job payload allowed the job type to be any string.&lt;/p&gt;

&lt;p&gt;But the producer always added the job as an inventory sync job.&lt;/p&gt;

&lt;p&gt;That creates a mismatch.&lt;/p&gt;

&lt;p&gt;A product sync payload could accidentally be queued as an inventory sync job.&lt;/p&gt;

&lt;p&gt;This is where TypeScript should help.&lt;/p&gt;

&lt;p&gt;Instead of using a loose string, the job type should be constrained.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SyncJobType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;INVENTORY_SYNC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PRODUCT_SYNC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or better, use an enum or constant map.&lt;/p&gt;

&lt;p&gt;The lesson:&lt;/p&gt;

&lt;p&gt;If the system only supports specific job types, the type system should enforce that.&lt;/p&gt;

&lt;p&gt;Loose strings make the code flexible, but also easier to break.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 6: Environment Variables Need Validation
&lt;/h2&gt;

&lt;p&gt;Some queue environment variables were typed as required strings, but the runtime code treated them as optional and provided defaults.&lt;/p&gt;

&lt;p&gt;There was also a risk with numeric environment variables.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;QUEUE_CONCURRENCY=abc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the code uses &lt;code&gt;Number(process.env.QUEUE_CONCURRENCY)&lt;/code&gt;, this becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kc"&gt;NaN&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That can create unexpected worker behavior.&lt;/p&gt;

&lt;p&gt;The better approach is to validate environment variables clearly.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;REDIS_URL&lt;/code&gt; is required, fail startup with a clear error.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;QUEUE_CONCURRENCY&lt;/code&gt; is optional, document the default.&lt;/li&gt;
&lt;li&gt;If a number is invalid, reject it early.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The lesson:&lt;/p&gt;

&lt;p&gt;Environment variables are part of the application contract. They need validation, not just typing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 7: Public Health Routes Can Leak Internal State
&lt;/h2&gt;

&lt;p&gt;The queue health endpoint exposed operational details publicly.&lt;/p&gt;

&lt;p&gt;Queue counts may not be secret, but they still reveal internal system information.&lt;/p&gt;

&lt;p&gt;For a public Shopify app URL, this matters.&lt;/p&gt;

&lt;p&gt;Health endpoints can expose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whether Redis is connected&lt;/li&gt;
&lt;li&gt;Whether workers are running&lt;/li&gt;
&lt;li&gt;Queue names&lt;/li&gt;
&lt;li&gt;Job counts&lt;/li&gt;
&lt;li&gt;Failure patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For internal monitoring, that is useful.&lt;/p&gt;

&lt;p&gt;For public access, that can become unnecessary exposure.&lt;/p&gt;

&lt;p&gt;The lesson:&lt;/p&gt;

&lt;p&gt;Operational routes should be protected.&lt;/p&gt;

&lt;p&gt;Possible solutions include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shared secret header&lt;/li&gt;
&lt;li&gt;Admin-only access&lt;/li&gt;
&lt;li&gt;Internal-only route&lt;/li&gt;
&lt;li&gt;Reduced public response&lt;/li&gt;
&lt;li&gt;Separate public and private health checks&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lesson 8: Small Untracked Files Matter
&lt;/h2&gt;

&lt;p&gt;There were accidental empty files in the project.&lt;/p&gt;

&lt;p&gt;They looked like command artifacts.&lt;/p&gt;

&lt;p&gt;This may seem small, but repository hygiene matters.&lt;/p&gt;

&lt;p&gt;Before committing, I should always check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And remove files that do not belong in the project.&lt;/p&gt;

&lt;p&gt;A clean commit should contain only intentional changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  My New Feature Completion Checklist
&lt;/h2&gt;

&lt;p&gt;After this review, my definition of “feature complete” has changed.&lt;/p&gt;

&lt;p&gt;Before committing a backend feature, I should verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run typecheck
npm run build
git status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I should manually confirm:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;App starts successfully&lt;/li&gt;
&lt;li&gt;Worker starts successfully&lt;/li&gt;
&lt;li&gt;Required environment variables are documented&lt;/li&gt;
&lt;li&gt;Invalid environment values fail clearly&lt;/li&gt;
&lt;li&gt;Health endpoint returns useful output&lt;/li&gt;
&lt;li&gt;Every queue has a consumer or processing strategy&lt;/li&gt;
&lt;li&gt;Failed jobs have a defined retry path&lt;/li&gt;
&lt;li&gt;Dead-letter jobs are visible for debugging&lt;/li&gt;
&lt;li&gt;Logs do not expose sensitive data&lt;/li&gt;
&lt;li&gt;Lockfile matches the selected package manager&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Takeaway
&lt;/h2&gt;

&lt;p&gt;Building the Redis Queue Foundation taught me that backend features are not just about writing logic.&lt;/p&gt;

&lt;p&gt;They are about designing reliable systems.&lt;/p&gt;

&lt;p&gt;A queue feature needs more than a producer and worker. It needs clear failure handling, strict types, reproducible dependencies, safe health checks, clean logs, and predictable runtime behavior.&lt;/p&gt;

&lt;p&gt;The biggest lesson:&lt;/p&gt;

&lt;p&gt;Code that works locally is not always production-ready.&lt;/p&gt;

&lt;p&gt;A production-ready feature must be easy to run, easy to debug, safe to expose, and hard to break.&lt;/p&gt;

&lt;p&gt;That is the real difference between just implementing a feature and engineering a feature properly.&lt;/p&gt;

</description>
      <category>software</category>
      <category>architecture</category>
      <category>typescript</category>
      <category>saas</category>
    </item>
    <item>
      <title>Understand Code Instead of Just Memorizing Syntax</title>
      <dc:creator>Dhruv Patel</dc:creator>
      <pubDate>Thu, 25 Jun 2026 02:28:14 +0000</pubDate>
      <link>https://dev.to/dhruvtechdev/understand-code-instead-of-just-memorizing-syntax-3gje</link>
      <guid>https://dev.to/dhruvtechdev/understand-code-instead-of-just-memorizing-syntax-3gje</guid>
      <description>&lt;p&gt;Many junior developers feel the same pressure:&lt;/p&gt;

&lt;p&gt;“I need to learn JavaScript.”&lt;br&gt;
“I need to learn TypeScript.”&lt;br&gt;
“I need to learn React.”&lt;br&gt;
“I need to learn Node.js.”&lt;br&gt;
“I need to learn testing, Git, DevOps, databases, deployment…”&lt;/p&gt;

&lt;p&gt;The list keeps growing.&lt;/p&gt;

&lt;p&gt;At some point, it starts feeling like you need to finish multiple full language books before you can call yourself a developer.&lt;/p&gt;

&lt;p&gt;But in real development, the goal is not to memorize everything.&lt;/p&gt;

&lt;p&gt;The goal is to understand code well enough to read it, explain it, debug it, improve it, and use it inside real projects.&lt;/p&gt;

&lt;p&gt;That is a much more practical target for juniors.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Problem Most Juniors Face
&lt;/h2&gt;

&lt;p&gt;A lot of beginners learn programming like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Watch a tutorial&lt;/li&gt;
&lt;li&gt;Copy the code&lt;/li&gt;
&lt;li&gt;Make it work&lt;/li&gt;
&lt;li&gt;Move to another tutorial&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This feels productive, but there is one issue:&lt;/p&gt;

&lt;p&gt;If the code breaks, they do not know why.&lt;/p&gt;

&lt;p&gt;That is the real gap.&lt;/p&gt;

&lt;p&gt;A junior developer does not need to know every advanced feature of a language immediately. But they should learn how to look at code and answer basic questions:&lt;/p&gt;

&lt;p&gt;What is this code trying to do?&lt;br&gt;
What is the input?&lt;br&gt;
What is the output?&lt;br&gt;
Where does the data change?&lt;br&gt;
What can break?&lt;br&gt;
How can I test it?&lt;br&gt;
How can I explain it?&lt;/p&gt;

&lt;p&gt;This is where real learning starts.&lt;/p&gt;
&lt;h2&gt;
  
  
  Learn Code in Three Layers
&lt;/h2&gt;

&lt;p&gt;Instead of learning everything randomly, juniors can divide their learning into three layers.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Language
&lt;/h3&gt;

&lt;p&gt;This is the foundation.&lt;/p&gt;

&lt;p&gt;For JavaScript or TypeScript, this includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;variables&lt;/li&gt;
&lt;li&gt;functions&lt;/li&gt;
&lt;li&gt;arrays&lt;/li&gt;
&lt;li&gt;objects&lt;/li&gt;
&lt;li&gt;loops&lt;/li&gt;
&lt;li&gt;conditionals&lt;/li&gt;
&lt;li&gt;async/await&lt;/li&gt;
&lt;li&gt;error handling&lt;/li&gt;
&lt;li&gt;modules&lt;/li&gt;
&lt;li&gt;types and interfaces&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You do not need to know every feature on day one. But you should be comfortable enough to write logic without copying every line.&lt;/p&gt;

&lt;p&gt;For example, you should be able to build small functions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;calculate cart total&lt;/li&gt;
&lt;li&gt;filter active users&lt;/li&gt;
&lt;li&gt;search products&lt;/li&gt;
&lt;li&gt;validate form data&lt;/li&gt;
&lt;li&gt;group items by category&lt;/li&gt;
&lt;li&gt;handle API response data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you can do this, your language foundation is growing.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Framework
&lt;/h3&gt;

&lt;p&gt;Frameworks help you build real applications faster.&lt;/p&gt;

&lt;p&gt;For frontend, this may be React or Next.js.&lt;br&gt;
For backend, this may be Node.js and Express.&lt;/p&gt;

&lt;p&gt;But frameworks are not magic. They are just structured ways to use your language.&lt;/p&gt;

&lt;p&gt;That is why juniors should not only ask:&lt;/p&gt;

&lt;p&gt;“How do I use React?”&lt;/p&gt;

&lt;p&gt;They should also ask:&lt;/p&gt;

&lt;p&gt;“What JavaScript concept is React using here?”&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;React state uses JavaScript values.&lt;br&gt;
React props use objects.&lt;br&gt;
React lists use arrays.&lt;br&gt;
API calls use promises and async/await.&lt;br&gt;
Forms use events and state updates.&lt;br&gt;
Components use functions.&lt;/p&gt;

&lt;p&gt;When you connect framework concepts back to the language, learning becomes easier.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Environment
&lt;/h3&gt;

&lt;p&gt;This is the part many juniors ignore, but companies care about it.&lt;/p&gt;

&lt;p&gt;Environment means knowing how code runs, breaks, and gets shipped.&lt;/p&gt;

&lt;p&gt;This includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;terminal&lt;/li&gt;
&lt;li&gt;Git and GitHub&lt;/li&gt;
&lt;li&gt;npm&lt;/li&gt;
&lt;li&gt;environment variables&lt;/li&gt;
&lt;li&gt;package.json&lt;/li&gt;
&lt;li&gt;debugging tools&lt;/li&gt;
&lt;li&gt;browser DevTools&lt;/li&gt;
&lt;li&gt;Postman&lt;/li&gt;
&lt;li&gt;deployment&lt;/li&gt;
&lt;li&gt;logs&lt;/li&gt;
&lt;li&gt;CI/CD basics&lt;/li&gt;
&lt;li&gt;Docker basics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A developer is not only someone who writes code.&lt;/p&gt;

&lt;p&gt;A developer should also know how to run code, debug code, test code, deploy code, and fix errors when something fails.&lt;/p&gt;
&lt;h2&gt;
  
  
  A Simple Checklist to Judge Code
&lt;/h2&gt;

&lt;p&gt;When juniors read or write code, they can use this checklist.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Correctness
&lt;/h3&gt;

&lt;p&gt;Does the code do what it is supposed to do?&lt;/p&gt;

&lt;p&gt;This is always the first question. Clean-looking code is useless if it does not solve the problem.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Readability
&lt;/h3&gt;

&lt;p&gt;Can another developer understand it quickly?&lt;/p&gt;

&lt;p&gt;Readable code is usually better than clever code.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Naming
&lt;/h3&gt;

&lt;p&gt;Are variables, functions, files, and components clearly named?&lt;/p&gt;

&lt;p&gt;Good names make code easier to understand.&lt;/p&gt;

&lt;p&gt;Bad example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.13&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Better example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculateTotalWithTax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.13&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second version explains itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Simplicity
&lt;/h3&gt;

&lt;p&gt;Is the code more complicated than needed?&lt;/p&gt;

&lt;p&gt;Junior developers sometimes try to write advanced-looking code. But in real teams, simple and understandable code is often better.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Edge Cases
&lt;/h3&gt;

&lt;p&gt;What can break?&lt;/p&gt;

&lt;p&gt;Ask questions like:&lt;/p&gt;

&lt;p&gt;What if the array is empty?&lt;br&gt;
What if the input is null?&lt;br&gt;
What if the API fails?&lt;br&gt;
What if a field is missing?&lt;br&gt;
What if the user enters invalid data?&lt;/p&gt;

&lt;p&gt;This habit makes your code stronger.&lt;/p&gt;
&lt;h3&gt;
  
  
  6. Error Handling
&lt;/h3&gt;

&lt;p&gt;What happens when something fails?&lt;/p&gt;

&lt;p&gt;For example, if an API request fails, the user should not see a broken screen. The application should handle the error properly.&lt;/p&gt;
&lt;h3&gt;
  
  
  7. Data Flow
&lt;/h3&gt;

&lt;p&gt;Can you follow how data enters, changes, and exits?&lt;/p&gt;

&lt;p&gt;This is one of the most important skills for juniors.&lt;/p&gt;

&lt;p&gt;In React, ask:&lt;/p&gt;

&lt;p&gt;Where does the data come from?&lt;br&gt;
Which component owns the state?&lt;br&gt;
Which component receives props?&lt;br&gt;
Where is the API called?&lt;br&gt;
Where is the result displayed?&lt;/p&gt;

&lt;p&gt;In backend code, ask:&lt;/p&gt;

&lt;p&gt;Where does the request come from?&lt;br&gt;
Which route handles it?&lt;br&gt;
Which controller runs?&lt;br&gt;
Which database operation happens?&lt;br&gt;
What response is returned?&lt;/p&gt;
&lt;h3&gt;
  
  
  8. Separation of Concerns
&lt;/h3&gt;

&lt;p&gt;Is each function, component, or file doing one clear job?&lt;/p&gt;

&lt;p&gt;If one function validates data, updates the database, sends emails, and formats the response, it may be doing too much.&lt;/p&gt;

&lt;p&gt;Good code is easier to change when responsibilities are separated.&lt;/p&gt;
&lt;h3&gt;
  
  
  9. Security
&lt;/h3&gt;

&lt;p&gt;Is user input handled safely?&lt;/p&gt;

&lt;p&gt;For junior developers, basic security awareness is enough to start:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;do not hardcode secrets&lt;/li&gt;
&lt;li&gt;use environment variables&lt;/li&gt;
&lt;li&gt;validate user input&lt;/li&gt;
&lt;li&gt;protect private routes&lt;/li&gt;
&lt;li&gt;check authentication&lt;/li&gt;
&lt;li&gt;check authorization&lt;/li&gt;
&lt;li&gt;never trust client-side data blindly&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  10. Tests
&lt;/h3&gt;

&lt;p&gt;Can you prove the code works?&lt;/p&gt;

&lt;p&gt;Tests do not need to be advanced in the beginning.&lt;/p&gt;

&lt;p&gt;Start by checking:&lt;/p&gt;

&lt;p&gt;Normal case&lt;br&gt;
Empty case&lt;br&gt;
Invalid input case&lt;br&gt;
Error case&lt;/p&gt;

&lt;p&gt;Even simple tests improve your thinking.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to Practice Daily
&lt;/h2&gt;

&lt;p&gt;Here is a simple daily routine for juniors.&lt;/p&gt;
&lt;h3&gt;
  
  
  Read Code
&lt;/h3&gt;

&lt;p&gt;Take one function or component and explain it in plain English.&lt;/p&gt;

&lt;p&gt;Write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Purpose:
Input:
Output:
Main logic:
What can break:
How I would improve it:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This builds code-reading skill.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modify Code
&lt;/h3&gt;

&lt;p&gt;Do not only copy tutorials.&lt;/p&gt;

&lt;p&gt;Change something.&lt;/p&gt;

&lt;p&gt;Add a feature.&lt;br&gt;
Rename variables.&lt;br&gt;
Split a function.&lt;br&gt;
Add validation.&lt;br&gt;
Improve error handling.&lt;br&gt;
Refactor repeated logic.&lt;/p&gt;

&lt;p&gt;Modification is where understanding becomes real.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debug Code
&lt;/h3&gt;

&lt;p&gt;Take working code and intentionally break one thing.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;wrong import&lt;/li&gt;
&lt;li&gt;missing return&lt;/li&gt;
&lt;li&gt;wrong API URL&lt;/li&gt;
&lt;li&gt;missing dependency in useEffect&lt;/li&gt;
&lt;li&gt;undefined variable&lt;/li&gt;
&lt;li&gt;wrong database field&lt;/li&gt;
&lt;li&gt;invalid token&lt;/li&gt;
&lt;li&gt;wrong route path&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then read the error and fix it.&lt;/p&gt;

&lt;p&gt;This is one of the fastest ways to become confident.&lt;/p&gt;

&lt;h3&gt;
  
  
  Explain Code
&lt;/h3&gt;

&lt;p&gt;After building something, explain it like this:&lt;/p&gt;

&lt;p&gt;“This component receives products as props. It stores the search text in state. When the user types, it filters the products array and displays only matching items.”&lt;/p&gt;

&lt;p&gt;If you cannot explain your code simply, you probably do not understand it fully yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Can You Say You Learned a Language?
&lt;/h2&gt;

&lt;p&gt;You do not need to know 100% of a language to say you know it.&lt;/p&gt;

&lt;p&gt;A practical definition is this:&lt;/p&gt;

&lt;p&gt;You know a language at a junior level when you can use it to build features, debug errors, read existing code, and explain your decisions.&lt;/p&gt;

&lt;p&gt;For JavaScript, that means you can work with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;arrays and objects&lt;/li&gt;
&lt;li&gt;functions&lt;/li&gt;
&lt;li&gt;async/await&lt;/li&gt;
&lt;li&gt;API calls&lt;/li&gt;
&lt;li&gt;error handling&lt;/li&gt;
&lt;li&gt;modules&lt;/li&gt;
&lt;li&gt;DOM or React usage&lt;/li&gt;
&lt;li&gt;common debugging problems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You are not finished learning the language. But you are useful with it.&lt;/p&gt;

&lt;p&gt;That is the real goal.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Juniors Should Focus On for Interviews
&lt;/h2&gt;

&lt;p&gt;For junior developer interviews, focus on practical fluency.&lt;/p&gt;

&lt;p&gt;You should be able to explain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;your projects&lt;/li&gt;
&lt;li&gt;your role in the project&lt;/li&gt;
&lt;li&gt;how frontend talks to backend&lt;/li&gt;
&lt;li&gt;how data moves through the app&lt;/li&gt;
&lt;li&gt;how authentication works&lt;/li&gt;
&lt;li&gt;how you handled errors&lt;/li&gt;
&lt;li&gt;how you tested the feature&lt;/li&gt;
&lt;li&gt;how you debugged a difficult issue&lt;/li&gt;
&lt;li&gt;what you would improve next&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should also practice basic coding problems using arrays, strings, objects, loops, and hash maps.&lt;/p&gt;

&lt;p&gt;The goal is not to sound like a senior engineer.&lt;/p&gt;

&lt;p&gt;The goal is to show that you can think clearly, learn fast, debug issues, and contribute to a codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;Junior developers do not need to learn everything at once.&lt;/p&gt;

&lt;p&gt;Start with this goal:&lt;/p&gt;

&lt;p&gt;Read code.&lt;br&gt;
Understand data flow.&lt;br&gt;
Build small features.&lt;br&gt;
Debug daily.&lt;br&gt;
Explain your work clearly.&lt;br&gt;
Improve code step by step.&lt;/p&gt;

&lt;p&gt;That is how syntax becomes skill.&lt;/p&gt;

&lt;p&gt;And that is how learning becomes real software development.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
      <category>softwaredevelopment</category>
    </item>
  </channel>
</rss>
