<?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: Enayet Rashid</title>
    <description>The latest articles on DEV Community by Enayet Rashid (@enayet_rashid_bd).</description>
    <link>https://dev.to/enayet_rashid_bd</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3844929%2F72c75322-d958-4c23-a935-96d12d19faea.png</url>
      <title>DEV Community: Enayet Rashid</title>
      <link>https://dev.to/enayet_rashid_bd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/enayet_rashid_bd"/>
    <language>en</language>
    <item>
      <title>🏦 Bridging Development and QA: My Journey from Code Design to Manual Testing Mastery</title>
      <dc:creator>Enayet Rashid</dc:creator>
      <pubDate>Tue, 31 Mar 2026 16:14:52 +0000</pubDate>
      <link>https://dev.to/enayet_rashid_bd/bridging-development-and-qa-my-journey-from-code-design-to-manual-testing-mastery-jnm</link>
      <guid>https://dev.to/enayet_rashid_bd/bridging-development-and-qa-my-journey-from-code-design-to-manual-testing-mastery-jnm</guid>
      <description>&lt;p&gt;&lt;strong&gt;How I Learned Testable Design by Breaking My Own ATM System:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg3l3f20b4llrm23qewp4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg3l3f20b4llrm23qewp4.jpg" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;** It Started With a "Working" System**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I built an ATM simulator. It worked. At least, that's what I thought.&lt;/p&gt;

&lt;p&gt;From a developer's perspective, everything looked fine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Log in ✔&lt;/li&gt;
&lt;li&gt;Check balance ✔&lt;/li&gt;
&lt;li&gt;Deposit and withdraw ✔&lt;/li&gt;
&lt;li&gt;Transfer funds ✔&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then I asked a simple question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I know this system actually works correctly?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That question changed everything.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;** The Illusion of "It Works"**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At first, I was testing informally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Try a valid input → works&lt;/li&gt;
&lt;li&gt;Try another valid input → works&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I felt confident. But I wasn't testing. I was confirming my own assumptions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;** The Turning Point: When I Tried to Test Properly**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I decided to approach my own system like a QA engineer.&lt;/p&gt;

&lt;p&gt;Not casually, but systematically.&lt;/p&gt;

&lt;p&gt;That's when I realised something uncomfortable:&lt;/p&gt;

&lt;p&gt;I didn't actually have clearly defined expected behaviour.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;** From Code to QA: Where Everything Became Real**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I created a separate repository dedicated to manual testing.&lt;/p&gt;

&lt;p&gt;Not random testing, but a structured QA workflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requirements&lt;/li&gt;
&lt;li&gt;Acceptance criteria&lt;/li&gt;
&lt;li&gt;Test plan&lt;/li&gt;
&lt;li&gt;Test scenarios&lt;/li&gt;
&lt;li&gt;Test cases&lt;/li&gt;
&lt;li&gt;Execution results&lt;/li&gt;
&lt;li&gt;Defects&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;** Step 1: Writing Requirements Changed Everything**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before writing a single test case, I had to answer:&lt;/p&gt;

&lt;p&gt;What exactly is the system supposed to do?&lt;/p&gt;

&lt;p&gt;So I formalised requirements like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication rules&lt;/li&gt;
&lt;li&gt;Deposit validation&lt;/li&gt;
&lt;li&gt;Withdrawal constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each requirement included clear acceptance criteria.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;** First Major Realisation**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I had written code before defining behaviour. That's backwards.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flyzyl6katrokz7uqu78i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flyzyl6katrokz7uqu78i.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;** Step 2: Designing Test Cases Exposed Gaps**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When I started writing test cases, something interesting happened.&lt;/p&gt;

&lt;p&gt;I began asking questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What happens if the user enters text instead of a number?&lt;/li&gt;
&lt;li&gt;What if they withdraw exactly the balance?&lt;/li&gt;
&lt;li&gt;What if they transfer to an invalid account?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These were not edge cases anymore. They were missing behaviours in my design.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;** The Moment My System Started Breaking**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When I executed my test scenarios, I found real issues.&lt;/p&gt;

&lt;p&gt;** Deposit Validation Issues**&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Non-numeric input was not handled clearly&lt;/li&gt;
&lt;li&gt;System behaviour was inconsistent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;** Transfer Usability Problem**&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Error messages were too generic&lt;/li&gt;
&lt;li&gt;The user did not know what went wrong&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;** Input Handling Problem**&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The system returned to the menu instead of re-prompting&lt;/li&gt;
&lt;li&gt;The user flow was broken&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These were not coding mistakes. They were design problems.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;** Test Execution Made It Real**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;** Execution Summary**&lt;/p&gt;

&lt;p&gt;From actual execution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Authentication → Passed&lt;/li&gt;
&lt;li&gt;✅ Balance → Passed&lt;/li&gt;
&lt;li&gt;❌ Deposit → Failed&lt;/li&gt;
&lt;li&gt;❌ Transfer → Failed&lt;/li&gt;
&lt;li&gt;❌ Input Handling → Failed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All backed by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Evidence screenshots&lt;/li&gt;
&lt;li&gt;Execution notes&lt;/li&gt;
&lt;li&gt;Scenario tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcouvr77mkdwlabpvm1pr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcouvr77mkdwlabpvm1pr.jpg" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;** Second Major Realisation**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Without execution tracking, testing is just opinion.&lt;/p&gt;

&lt;p&gt;** Step 3: Defects Told Me the Truth**&lt;/p&gt;

&lt;p&gt;I documented each defect clearly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Steps to reproduce&lt;/li&gt;
&lt;li&gt;Expected vs actual behaviour&lt;/li&gt;
&lt;li&gt;Evidence&lt;/li&gt;
&lt;li&gt;Impact&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I did not use tools like Jira. I did not need them. Because the value was not in the tool, it was in the clarity of thinking.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;** The Most Important Lesson: Design Impacts Testing**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At this point, something became very clear.&lt;/p&gt;

&lt;p&gt;** Developer vs QA Mindset**&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Developer Thinking&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;QA Thinking&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;It works&lt;/td&gt;
&lt;td&gt;What can break?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Focus on happy path&lt;/td&gt;
&lt;td&gt;Focus on edge cases&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code-focused&lt;/td&gt;
&lt;td&gt;Behaviour-focused&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;** Critical Insight**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Poor design creates hidden defects. Testing simply reveals them.&lt;/p&gt;

&lt;p&gt;** SDLC Reflection: Where This Matters in Real Life**&lt;/p&gt;

&lt;p&gt;This experience made me think beyond my project.&lt;/p&gt;

&lt;p&gt;** What Happens in Real Projects?**&lt;/p&gt;

&lt;p&gt;If you skip proper planning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requirements are unclear&lt;/li&gt;
&lt;li&gt;Test cases are inconsistent&lt;/li&gt;
&lt;li&gt;Bugs are discovered late&lt;/li&gt;
&lt;li&gt;Fixes become expensive&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;** Cost of Poor Planning**&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developers rework logic&lt;/li&gt;
&lt;li&gt;Testers rewrite cases&lt;/li&gt;
&lt;li&gt;Deadlines slip&lt;/li&gt;
&lt;li&gt;Confidence drops&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;** Looking Back at My ATM Design**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now I see my system differently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before Testing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This works fine&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After Testing&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validation logic incomplete&lt;/li&gt;
&lt;li&gt;Error messaging unclear&lt;/li&gt;
&lt;li&gt;User flow inconsistent&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;** The Shift That Changed Everything**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I stopped asking: Does it work?&lt;br&gt;
And started asking: Can it fail safely?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;** What This Means Going Forward**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because I designed the system with separation of concerns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I can now add an API layer&lt;/li&gt;
&lt;li&gt;I can automate tests using Pytest&lt;/li&gt;
&lt;li&gt;I can introduce UI automation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is no longer just a project. It is a foundation for real QA and automation work.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;** Final Takeaways**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Writing code is not enough&lt;/li&gt;
&lt;li&gt;Testability is a design decision&lt;/li&gt;
&lt;li&gt;Requirements drive testing&lt;/li&gt;
&lt;li&gt;Testing reveals design flaws&lt;/li&gt;
&lt;li&gt;Real QA is structured, not random&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;** Closing Thought**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I started this project to build an ATM system, but I ended up learning something much bigger. The moment I stopped treating QA as something you do after coding and started treating it as a design constraint from the beginning, my code improved before I even wrote it. I didn't just learn how to test software - I learned that the most valuable test cases are the ones that make you realise your design was incomplete&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;** Repositories**&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;ATM Simulator&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/enayetrashid/atm-simulator" rel="noopener noreferrer"&gt;https://github.com/enayetrashid/atm-simulator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Manual Testing Practice&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/enayetrashid/manual-testing-practice" rel="noopener noreferrer"&gt;https://github.com/enayetrashid/manual-testing-practice&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>testing</category>
      <category>qa</category>
      <category>automation</category>
    </item>
    <item>
      <title>From if Statements to Classes: How Refactoring Taught Me Testable Code</title>
      <dc:creator>Enayet Rashid</dc:creator>
      <pubDate>Fri, 27 Mar 2026 11:12:28 +0000</pubDate>
      <link>https://dev.to/enayet_rashid_bd/from-if-statements-to-classes-how-refactoring-taught-me-testable-code-26a0</link>
      <guid>https://dev.to/enayet_rashid_bd/from-if-statements-to-classes-how-refactoring-taught-me-testable-code-26a0</guid>
      <description>&lt;p&gt;I am a self-taught learner. So when I decided to build a Python calculator, I didn't start with classes or design patterns. I started with the messiest, most beginner thing possible - everything crammed into one script. And honestly? That was the right decision.&lt;/p&gt;

&lt;p&gt;This article is about how I evolved that calculator through three versions, and what each step taught me about writing code that's actually testable - which matters a lot when you're learning QA automation like I am.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/enayetrashid/python-calculator-evolution" rel="noopener noreferrer"&gt;https://github.com/enayetrashid/python-calculator-evolution&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgft108iegwkmpba7z6md.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgft108iegwkmpba7z6md.jpeg" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Version 1 - The "Just Make It Work" Phase
&lt;/h2&gt;

&lt;p&gt;My first version was pure chaos by design. No functions, no classes; just raw logic from top to bottom.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enter first number: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enter second number: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enter operation (+, -, *, /): &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;+&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It worked. But the moment I asked myself &lt;em&gt;"how do I test this?"&lt;/em&gt; I had no answer. You can't test code that demands user input just to run. This was my first real lesson:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If input and logic live together, testing becomes nearly impossible.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Version 2 - Introducing Functions
&lt;/h2&gt;

&lt;p&gt;I pulled the calculation logic out into separate functions. A small change - but it changed everything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;subtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I could write an actual test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_add&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&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="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No input prompts. No manual interaction. Just pure logic I could verify instantly. This felt like a superpower.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The lesson:&lt;/strong&gt; Functions are the foundation of testable code. If you can't call it in isolation, you can't test it properly.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Version 3 - Moving to OOP
&lt;/h2&gt;

&lt;p&gt;Finally I wrapped everything in a class and added proper error handling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ZeroDivisionError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Division by zero&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;divide&lt;/code&gt; method was a turning point for me. Adding that guard clause meant I could now test &lt;em&gt;failure scenarios&lt;/em&gt; too - not just the happy path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_divide_by_zero&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;calc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;ZeroDivisionError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;calc&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The lesson:&lt;/strong&gt; OOP isn't just about organisation - it's about making your code extensible and testable at scale.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Why This Matters Beyond the Calculator
&lt;/h2&gt;

&lt;p&gt;I'm learning QA automation, and this little project taught me something that no tutorial explained clearly:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The structure of code directly affects how easy it is to test.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In real automation work with tools like Pytest or Playwright, you never test everything in one place. You separate test logic, business logic, and test data. This calculator evolved through exactly that same pattern:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;th&gt;Structure&lt;/th&gt;
&lt;th&gt;Testability&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Version 1&lt;/td&gt;
&lt;td&gt;Everything inline&lt;/td&gt;
&lt;td&gt;Nearly impossible to test&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Version 2&lt;/td&gt;
&lt;td&gt;Functions&lt;/td&gt;
&lt;td&gt;Testable in isolation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Version 3&lt;/td&gt;
&lt;td&gt;OOP&lt;/td&gt;
&lt;td&gt;Scalable and extensible&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Start simple&lt;/strong&gt; - but don't stay simple&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refactoring is a skill&lt;/strong&gt;, not just a task&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testability should guide your design decisions&lt;/strong&gt; from the beginning&lt;/li&gt;
&lt;li&gt;Even the smallest projects can teach big engineering concepts&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;This wasn't really about building a calculator. It was about learning to think like someone who cares about quality - not just getting something to run, but building it so it &lt;em&gt;can be verified.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the simplest project that taught you something fundamental? I'd love to hear it in the comments.&lt;/strong&gt; &lt;/p&gt;




</description>
      <category>python</category>
      <category>unittest</category>
      <category>refactoring</category>
      <category>oop</category>
    </item>
  </channel>
</rss>
