<?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: Muhammad Refel Hidayatullah</title>
    <description>The latest articles on DEV Community by Muhammad Refel Hidayatullah (@hrefel).</description>
    <link>https://dev.to/hrefel</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%2F326050%2F9d421a5b-60a2-4c79-98e5-9633fc09ce3c.jpeg</url>
      <title>DEV Community: Muhammad Refel Hidayatullah</title>
      <link>https://dev.to/hrefel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hrefel"/>
    <language>en</language>
    <item>
      <title>Vibe Coding Tools - Vibespecs CLI</title>
      <dc:creator>Muhammad Refel Hidayatullah</dc:creator>
      <pubDate>Fri, 31 Oct 2025 03:00:58 +0000</pubDate>
      <link>https://dev.to/hrefel/vibe-coding-tools-vibespecs-cli-4oia</link>
      <guid>https://dev.to/hrefel/vibe-coding-tools-vibespecs-cli-4oia</guid>
      <description>&lt;h2&gt;
  
  
  The Era of Generative Coding — and Why I Finally Gave In
&lt;/h2&gt;

&lt;p&gt;I’ve never been a big fan of what people now call vibe coding.&lt;br&gt;
To me, coding has always been about clarity, structure, and intent — not just getting something to work because an AI said so.&lt;/p&gt;

&lt;p&gt;But here’s the thing: in tech, if you don’t evolve, you get left behind.&lt;br&gt;
That’s just &lt;strong&gt;natural selection&lt;/strong&gt; in motion.&lt;/p&gt;

&lt;p&gt;So instead of resisting the wave, I decided to understand it.&lt;br&gt;
I started exploring how AI can be used not just as a helper, but as a collaborator in building better systems.&lt;/p&gt;

&lt;p&gt;And that’s how I found myself deep in the world of AI Generative Code — or, as people casually call it today, vibe coding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A CLI for Machine-Friendly Specs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the biggest challenges I’ve noticed when working with AI tools is communication.&lt;br&gt;
Machines don’t “understand” code the way humans do — they interpret patterns, context, and structure.&lt;/p&gt;

&lt;p&gt;So, I started building a CLI tool that can generate machine-readable specs, designed to help both developers and AI models speak the same language.&lt;/p&gt;

&lt;p&gt;This CLI integrates with multiple AI providers to generate consistent and detailed specification documents.&lt;br&gt;
Think of it as a translator — it turns human intent into structured instructions that AI can process effectively.&lt;/p&gt;

&lt;p&gt;The goal isn’t to replace developers.&lt;br&gt;
It’s to make sure that when we code with AI, the results are predictable, explainable, and high-quality.&lt;/p&gt;

&lt;p&gt;Output support JSON, YAML &amp;amp; TOON (Token Object Oriented Notation)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/johannschopplich/toon" rel="noopener noreferrer"&gt;More About Toon&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hybrid Processing&lt;/strong&gt;: Combines heuristic parsing with AI refinement for optimal accuracy and speed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Wizard Mode&lt;/strong&gt;: Guided interactive refinement when AI is unavailable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple AI Providers&lt;/strong&gt;: Supports OpenAI, Anthropic Claude, OpenRouter, and GLM (ZhipuAI)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intelligent Caching&lt;/strong&gt;: LRU cache minimizes redundant API calls&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible Configuration&lt;/strong&gt;: Environment variables, &lt;code&gt;.env&lt;/code&gt; files, and config files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation&lt;/strong&gt;: Built-in spec validation against schema&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple Formats&lt;/strong&gt;: Output to JSON, YAML, or TOON (Token-Oriented Object Notation)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;We’re now entering an era where how we write code matters less than how well we can describe it.&lt;br&gt;
If we can teach the machine to understand our intent — that’s where true collaboration begins.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/vibespec-cli" rel="noopener noreferrer"&gt;Learn More About Installation &amp;amp; Usage Here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>cli</category>
      <category>tooling</category>
      <category>showdev</category>
      <category>ai</category>
    </item>
    <item>
      <title>HttpOnly Cookies: A Secure Solution for Sensitive Data</title>
      <dc:creator>Muhammad Refel Hidayatullah</dc:creator>
      <pubDate>Mon, 03 Feb 2025 10:40:56 +0000</pubDate>
      <link>https://dev.to/hrefel/httponly-cookies-a-secure-solution-for-sensitive-data-25ck</link>
      <guid>https://dev.to/hrefel/httponly-cookies-a-secure-solution-for-sensitive-data-25ck</guid>
      <description>&lt;p&gt;Throughout my 5-year career in frontend development, almost every application I built utilized JWT Tokens. Typically, these tokens were stored in the browser’s storage, such as localStorage or sessionStorage. Initially, I felt comfortable with this method due to its simplicity and convenience, and many articles also used localStorage or sessionStorage as the standard example.&lt;/p&gt;

&lt;p&gt;However, as I gained a deeper understanding of hacker tactics, I began to question the security of using localStorage, especially for sensitive data. This led me to explore HttpOnly Cookies, which turned out to be the best solution for securely storing JWT Tokens.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;HTTPOnly cookies are cookies that have the HTTPOnly attribute, which prevents client-side scripts from accessing the data stored in the cookie.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why should we implement HttpOnly Cookies?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Protection against XSS (Cross-Site Scripting):&lt;/strong&gt;&lt;br&gt;
HttpOnly Cookies cannot be accessed via JavaScript, providing better security against XSS attacks.&lt;br&gt;
&lt;strong&gt;2. Automatic management by the browser:&lt;/strong&gt; Cookies are automatically sent with every HTTP request to the appropriate domain, reducing implementation complexity.&lt;br&gt;
&lt;strong&gt;3. Effortless for frontend developers:&lt;/strong&gt; Frontend developers no longer need to manage JWT Tokens or store them in the browser’s storage, reducing the client-side security management burden.&lt;br&gt;
&lt;strong&gt;4. Security attribute settings:&lt;/strong&gt; Attributes such as Secure, SameSite, and HttpOnly strengthen data protection by restricting how data can be accessed and transmitted.&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%2F33tqmpnj0tzbg1sn5s3r.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%2F33tqmpnj0tzbg1sn5s3r.png" alt="Image Sequence HttpOnly" width="800" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Client -&amp;gt; Server: Login Request&lt;/strong&gt;
The client sends a login request containing the username and password to the server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server -&amp;gt; AuthService: Validate credentials&lt;/strong&gt;
The server forwards the credentials (username and password) to the authentication service for validation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AuthService -&amp;gt; DB: Query user by username&lt;/strong&gt;
The authentication service queries the database to retrieve the user record based on the provided username.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DB → AuthService: Return user record&lt;/strong&gt;
The database returns the user record (e.g., hashed password, role, etc.).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AuthService -&amp;gt; Server: Return user authentication status&lt;/strong&gt;
The authentication service returns the authentication status to the server (valid or invalid).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server -&amp;gt; JWTValidator: Generate JWT&lt;/strong&gt;
If the credentials are valid, the server requests the JWT Validator to generate a JWT based on the user’s data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JWTValidator → Server: Return JWT&lt;/strong&gt;
The JWT Validator generates and returns the JWT to the server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server -&amp;gt; Client: Set HttpOnly Cookie with JWT&lt;/strong&gt;
The server sends the JWT to the client as an HttpOnly cookie, which is stored in the browser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client -&amp;gt; Server: Authenticated Request&lt;/strong&gt;
The client sends an authenticated request to the server, automatically including the HttpOnly cookie with the JWT.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server -&amp;gt; JWTValidator: Validate JWT from Cookie&lt;/strong&gt;
The server sends the JWT from the cookie to the JWT Validator for validation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JWTValidator → Server: Return JWT validation status&lt;/strong&gt;
The JWT Validator checks the token’s validity. If valid, the request is processed; otherwise, a 401 Unauthorized response is sent to the client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;alt Valid JWT&lt;/strong&gt;
If the JWT is valid, the server processes the request (e.g., fetching data or resource) and returns the response to the client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;else Invalid JWT&lt;/strong&gt;
If the JWT is invalid, the server responds with a 401 Unauthorized status.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;By implementing HttpOnly Cookies, we can enhance the security of our website and protect users from potential attacks, particularly those related to XSS. I hope this article provides valuable insights. If you have any suggestions or more practical approaches, feel free to discuss them with me. Keep learning and stay curious!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://github.com/hrefel/go-login" rel="noopener noreferrer"&gt;PoC&lt;/a&gt; &lt;/p&gt;

</description>
      <category>security</category>
      <category>jwt</category>
      <category>webdev</category>
      <category>cookies</category>
    </item>
    <item>
      <title>Summary of TDD that I tried to learn</title>
      <dc:creator>Muhammad Refel Hidayatullah</dc:creator>
      <pubDate>Mon, 27 Jan 2025 14:40:53 +0000</pubDate>
      <link>https://dev.to/hrefel/summary-of-tdd-that-i-tried-to-learn-3cji</link>
      <guid>https://dev.to/hrefel/summary-of-tdd-that-i-tried-to-learn-3cji</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;1. The Cycle of TDD&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;- Write a Test First&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Before writing implementation code, write a test that specifies how the code should behave. This test will typically fail at first because the code hasn't been implemented yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Write Just Enough Code&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Write only the code necessary to make the test pass. Do not add features beyond the scope of the test.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Refactor&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Once the test passes, refactor the code to improve its quality without changing its functionality.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;2. TDD Mindset&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;- Start with Failure (Fail First):&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Get used to writing tests for features that do not yet exist. This requires discipline and the mindset that "failure is normal" at the beginning of the process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Small, Focused, and Iterative&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Avoid trying to implement large features all at once. TDD encourages breaking work into small parts and focusing on one thing at a time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Design by Tests&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
TDD is not just about writing tests; it's also about design. Writing tests before code forces you to think about the best way to design APIs or functions to make them easy to test.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;3. Testing Approaches in TDD&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;- Unit Test&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Focus on the smallest unit of code, typically a function or class.  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ensure tests are deterministic (the same result every time they run).
&lt;/li&gt;
&lt;li&gt;Use mocking or stubbing to isolate external dependencies.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;- Integration Test&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Test interactions between multiple units.  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ensure modules work well together.
&lt;/li&gt;
&lt;li&gt;Focus on data flow between components.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;- End-to-End (E2E) Test&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Test the entire system from the user's perspective.  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use this only for key features, as these tests are time-consuming.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;4. Strategies to Avoid TDD Failures&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Write Accurate Tests&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Don't just test the "happy path." Write tests for edge cases or error scenarios:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zero values (0)
&lt;/li&gt;
&lt;li&gt;Empty strings
&lt;/li&gt;
&lt;li&gt;Invalid inputs (e.g., null or undefined)
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;- Use Coverage Reports&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Ensure your code is thoroughly tested. Use tools like Istanbul, Jest, or SonarQube to check test coverage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Manage Dependencies&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Avoid tight coupling between modules. Use techniques like:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mocking to replace dependencies with fake versions.
&lt;/li&gt;
&lt;li&gt;Inversion of Control (IoC) or dependency injection to make components easier to test.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;5. Organizing Tests&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;a. Clear Test Structure&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Use the Arrange-Act-Assert (AAA) format:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Arrange&lt;/em&gt;: Set up all data, dependencies, or initial conditions.
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Act&lt;/em&gt;: Call the function or perform the action you want to test.
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Assert&lt;/em&gt;: Verify that the result matches the expected outcome.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;b. Use Descriptive Naming&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Test names should be clear and explain what is being tested.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;c. Organize Test Folders&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Keep tests in a well-organized folder structure.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;6. Design Principles for TDD&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;a. Single Responsibility Principle (SRP)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Ensure functions or classes have only one responsibility, making them easier to test.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;b. Open/Closed Principle&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Design components to be extensible without modifying existing code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;c. Dependency Injection&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Avoid creating direct dependencies inside a class. Instead, inject dependencies from the outside.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;7. Advanced Concepts in TDD&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;a. Test Doubles&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mock&lt;/strong&gt;: Replace real objects with fake ones to control behavior and verify interactions.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stub&lt;/strong&gt;: Provide fake responses for a function.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spy&lt;/strong&gt;: Track how a function is called.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;b. Behavior-Driven Development (BDD)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
An advanced form of TDD, where tests are written in a human-readable language, often using frameworks like Cucumber.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Scenario: Adding two numbers
Given I have numbers 2 and 3
When I sum the numbers
Then the result should be 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;8. Advanced Tips&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Outside-In Development (London School TDD)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Approach&lt;/strong&gt;: Start with high-level tests like integration or acceptance tests before moving to unit testing.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Main Principle&lt;/strong&gt;: Focus on behavior rather than implementation. Develop the system based on how components should interact.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Start with testing an API endpoint (e.g., REST or GraphQL), then move to the service, repository, and class-level implementation.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid over-engineering by ensuring only necessary code is written.
&lt;/li&gt;
&lt;li&gt;Focus on functional outcomes.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Mutation Testing&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Concept&lt;/strong&gt;: Evaluate test quality by introducing small changes (mutations) in the source code and checking if tests catch those changes.  &lt;/p&gt;

&lt;p&gt;If tests don't fail after a mutation, it indicates a lack of coverage or precision.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript: Stryker
&lt;/li&gt;
&lt;li&gt;Java: Pitest
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Measure how robust your tests are against code changes.
&lt;/li&gt;
&lt;li&gt;Identify high-risk areas for bugs.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Mocking and Stubbing Best Practices&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When testing components that depend on external services or APIs, use mocking and stubbing.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;General Principles:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use mocks to verify interactions (e.g., whether a method was called).
&lt;/li&gt;
&lt;li&gt;Use stubs to provide fixed responses (dummy data) from dependencies.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Property-Based Testing&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Concept&lt;/strong&gt;: Instead of testing specific cases, define general properties or rules that must always hold true.  &lt;/p&gt;

&lt;p&gt;Example: "The result of merging two arrays must always equal the combined length of both arrays."  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript: Fast-check
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Discover hidden bugs by testing many input combinations.
&lt;/li&gt;
&lt;li&gt;Ideal for complex algorithms like sorting or encryption.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Golden Master Testing&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Concept&lt;/strong&gt;: Used for legacy systems or complex code without prior documentation or tests.  &lt;/p&gt;

&lt;p&gt;Take a snapshot of the current behavior or output (golden master) and use it as a baseline for future tests.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enables refactoring of old systems without breaking functionality.
&lt;/li&gt;
&lt;li&gt;Highly effective for large or monolithic systems.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6. Contract Testing&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Concept&lt;/strong&gt;: Ensure that the contract between two services, such as an API and its consumer, is not broken.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pact (for API contract testing).
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Increases confidence when making changes or iterating on dependent services.
&lt;/li&gt;
&lt;li&gt;Reduces integration risks.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;7. Exploratory Testing with TDD&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Approach&lt;/strong&gt;: Combine TDD principles with manual exploration for new features or experimental algorithms.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Method:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write initial tests to "lock in" known behavior.
&lt;/li&gt;
&lt;li&gt;Use additional tests to explore how the code reacts to new inputs or scenarios.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uncover edge cases that might have been missed.
&lt;/li&gt;
&lt;li&gt;Accelerate validation of new functionality.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;8. Delayed Implementation&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
For cases where a feature or function cannot yet be implemented (e.g., due to unfinished dependencies), use a test placeholder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe('New Feature', () =&amp;gt; {
  it('should handle specific edge case (TODO: implement)', () =&amp;gt; {
    // Tes sementara
    expect(true).toBe(true); 
  });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reminds the team to complete pending parts.
&lt;/li&gt;
&lt;li&gt;Breaks work into manageable steps.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;9. Working with Legacy Code&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If legacy code lacks tests:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add Characterization Tests to "lock in" current behavior.
&lt;/li&gt;
&lt;li&gt;Write tests for small parts of the code you plan to modify.
&lt;/li&gt;
&lt;li&gt;Gradually refactor while ensuring tests pass.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Introduces TDD into systems that were not initially designed for it.
&lt;/li&gt;
&lt;li&gt;Reduces refactoring risks in legacy systems.
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tdd</category>
      <category>methodology</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Code commit best practice with commitizen &amp; pre-commit</title>
      <dc:creator>Muhammad Refel Hidayatullah</dc:creator>
      <pubDate>Thu, 24 Aug 2023 10:26:01 +0000</pubDate>
      <link>https://dev.to/hrefel/code-commit-best-practice-with-commitizen-pre-commit-18ae</link>
      <guid>https://dev.to/hrefel/code-commit-best-practice-with-commitizen-pre-commit-18ae</guid>
      <description>&lt;p&gt;In this opportunity, I will share about Git hooks, Commitizen, and ESLint for linting. Coincidentally, on this occasion, I will be using Angular projects.&lt;/p&gt;

&lt;p&gt;Let's say we already have Angular projects. And then, you need to install several dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D husky eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;STEP 2&lt;/strong&gt;&lt;br&gt;
You need to setup husky in your project with run this command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx husky install 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That command will generate the &lt;u&gt;.husky/pre-commit&lt;/u&gt; file. pre-commit file will look 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;#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npm run test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;STEP 3&lt;/strong&gt;&lt;br&gt;
Setup &lt;u&gt;&lt;a href="https://www.npmjs.com/package/commitizen" rel="noopener noreferrer"&gt;commitizen&lt;/a&gt;&lt;/u&gt; for template commit message. This is a beautiful feature to organize commit messages, especially when working with a fairly large team. For setup commitizen you need to run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i commitizen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and add this on your &lt;u&gt;package.json&lt;/u&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"config": {
    "commitizen": {
      "path": "cz-conventional-changelog",
      "jiraOptional": true
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't finished yet, you need to run the following script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx husky add .husky/prepare-commit-msg "exec &amp;lt; /dev/tty &amp;amp;&amp;amp; git cz --hook || true"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If successful, it will create a new file inside the .husky/prepare-commit-msg folder. You can test this by running the commit with empty message:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git commit -am ""&lt;/code&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%2Fpfcm55mf3i2xbmg39hd4.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%2Fpfcm55mf3i2xbmg39hd4.png" alt="result" width="800" height="143"&gt;&lt;/a&gt;&lt;br&gt;
and choose one of the options. in this case i will choose feature&lt;/p&gt;

&lt;p&gt;next, you need to fill scope of changes.&lt;br&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%2Fni2bfqufpcez5y141r98.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%2Fni2bfqufpcez5y141r98.png" alt="scope changes" width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;next, you need to fill short description about changes&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%2Fk2dmhr72lm7oeil3hbsl.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%2Fk2dmhr72lm7oeil3hbsl.png" alt="short desc" width="800" height="183"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and then, they provide for longer description. For this input, it's optional, you can leave it empty.&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%2Fz6bu66ishvgfbpuc7xfv.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%2Fz6bu66ishvgfbpuc7xfv.png" alt="long desc" width="800" height="185"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And next, they ask whether there are any breaking changes or if there will be any other open issues. If you choose 'y', they will ask for your explanation.&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%2Fltmeggstbii7vq39uaho.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%2Fltmeggstbii7vq39uaho.png" alt="Image description" width="800" height="198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;commit message on gitlab will look like this:&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%2F2e972ui8cyxf5airiylw.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%2F2e972ui8cyxf5airiylw.png" alt="sample gitlab" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It appears tidy and easy to understand for documentation or your code reviewer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This feature is very helpful for describing what you're doing with code changes and greatly assists code reviewers.&lt;br&gt;
for Linter git hooks / pre commit will posted at next article.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>githooks</category>
      <category>commitizen</category>
      <category>husky</category>
      <category>git</category>
    </item>
  </channel>
</rss>
