Author Archives: mgl1990

Sprint Retrospective – Sprint-1

Evidence of Activity on GitLab

  1. Meeting with Customer to Identify Categories
    • A .js file named categories.js was built to help my peers start testing different category structures.
  2. Data Extraction for TeaSparty Project
    • The USDA FoodData Central downloadable data was extracted to build a comprehensive database.
  3. Database Optimization
    • The original database file was over 3.2GB and contained multiple unnecessary fields.
    • A Java file was developed to remove unnecessary fields such as foodNutrients, nutrients, rank, protein, and their respective IDs.
    • Successfully reduced the database from 3.2GB to 0.7GB, making it more manageable for our project.

Reflection on What Worked Well

  1. Customer Collaboration
    • Meeting with the customer to identify category requirements ensured that the project met their needs effectively.
    • The creation of categories.js provided a starting point for peer testing, helping streamline future work.
  2. Database Optimization
    • By removing unnecessary fields, the database was significantly reduced in size, improving efficiency.
    • The pre-cleaning process helped identify redundant fields early on, making subsequent steps more manageable.

Reflection on What Didn’t Work Well

  1. API Call Extraction Issue
    • Initially, I attempted to extract the database via API calls but encountered a limitation: API calls only supported retrieving 100 items at a time, whereas there were over 100 pages to extract.
    • Researching solutions, I found that automation was the best approach, but due to my lack of expertise in automation, I couldn’t implement it effectively.
  2. Challenges in Categorizing Products
    • A Java file was created to categorize all products, but it was crashing due to issues with object field descriptions containing multiple nested quotes.
    • Example issue: "description":"ORIGINAL SWEET & SMOKY BAR \"\"B\"\" \"\"Q\"\" SAUCE, ORIGINAL".
    • As a workaround, I manually cleaned some of the problematic entries but am still looking for a better solution.

Reflection on What Changes Could Be Made to Improve as a Team

  • Better Communication
    • Ensuring consistent updates within the team would help synchronize our work and avoid redundant efforts.
    • More frequent check-ins to discuss roadblocks and potential solutions could improve efficiency.

Reflection on What Changes Could Be Made to Improve as an Individual

  • Increase Work Hours on the Project
    • Spending more time on the project will allow my peers to see my progress and provide feedback earlier.
  • Dependency on Others’ Progress
    • I am currently waiting for Alex to finish the dev container. In the meantime, I am focusing on cleaning the db.json file so I can upload it as soon as possible.

Apprenticeship Pattern: “Expose Your Ignorance”

Summary of the Pattern

The “Expose Your Ignorance” pattern from the Apprenticeship Patterns book emphasizes acknowledging one’s knowledge gaps and actively seeking to learn. It encourages transparency about what you don’t know while making efforts to bridge those gaps.

Why This Pattern Was Selected

During this sprint, I faced challenges with API automation and data cleaning that slowed my progress. If I had openly acknowledged my lack of expertise in automation sooner, I could have sought help from peers or external resources earlier in the sprint. This pattern aligns with my experience because it highlights the importance of being upfront about knowledge gaps and taking proactive steps to fill them.

How This Pattern Would Have Changed My Behavior

Had I followed this pattern earlier in the sprint:

  • I would have sought advice from team members or forums on API automation instead of spending excessive time trying to figure it out alone.
  • I would have explored existing libraries or tools for handling JSON parsing issues more efficiently instead of resorting to manual cleaning.

Conclusion

This sprint provided valuable lessons in data handling, API limitations, and the importance of seeking help when needed. Moving forward, I plan to improve communication within the team, allocate more time to the project, and be more proactive in addressing technical challenges. Applying the “Expose Your Ignorance” pattern will help me become a more effective contributor in future sprints.

From the blog Discoveries in CS world by mgl1990 and used with permission of the author. All other rights reserved by the author.

The beginning of a Journey of a Software Craftsman: Reflections on Chapter 1 of Apprenticeship Patterns

The path to becoming a skilled software developer is not just about learning programming languages or mastering frameworks—it’s about embracing a mindset of continuous learning, humility, and craftsmanship. Chapter 1 of Apprenticeship Patterns: Guidance for the Aspiring Software Craftsman by Dave Hoover and Adewale Oshineye sets the foundation for this philosophy, introducing readers to the idea of software development as a lifelong journey of growth.

One of the most compelling aspects of this chapter is its focus on the concept of apprenticeship in software development. Unlike traditional education or even structured corporate training, an apprenticeship mindset encourages developers to seek knowledge actively, engage with mentors, and build real-world experience through deliberate practice. The book compares software craftsmanship to traditional guilds, where newcomers learn by doing, gradually refining their skills under the guidance of experienced practitioners.

The emphasis on deliberate practice particularly resonated with me. It’s easy to fall into the trap of writing code every day and assuming that practice alone leads to mastery. However, the book suggests that true improvement comes from purposeful and reflective practice—analyzing mistakes, challenging oneself, and continuously pushing the boundaries of one’s abilities. This idea shifted my perspective on how I approach learning new technologies and refining my existing skills.

Before reading this chapter, I viewed my professional growth in software development as something that happens naturally over time—an accumulation of experience gained from projects and exposure to different technologies. However, Apprenticeship Patterns made me realize that growth must be intentional. It’s not enough to just work on projects; I need to actively seek out challenges, solicit feedback, and set concrete learning goals to accelerate my progress.

Another takeaway that impacted my mindset is the importance of humility. The book stresses that being a software craftsman requires accepting that there will always be more to learn. I found this particularly valuable because it aligns with the idea of the beginner’s mind—approaching every problem, regardless of experience, with curiosity and openness rather than arrogance.

P

While I found the chapter insightful, one point that I questioned was the romanticization of apprenticeship as a primary learning model. While mentorship and hands-on learning are invaluable, not everyone has access to experienced developers willing to guide them. In today’s fast-paced software industry, many developers are self-taught through online courses, coding boot camps, and open-source contributions. While the book acknowledges that different learning paths exist, I think it could have placed more emphasis on alternative ways to develop craftsmanship outside of the traditional mentor-apprentice model.

Which Chapters Seem Most Relevant?

From a quick glance at the table of contents, the chapters that seem most relevan that caught me:

  • This seems crucial for maintaining motivation and engagement in the field. Passion is what drives deep learning.
  • I’m interested in how the book suggests balancing learning new, complex topics while also reinforcing foundational skills.
  • This chapter likely discusses the tension between personal growth as a developer versus career advancement, a topic that resonates deeply with me as I navigate my own path.

Chapter 1 of Apprenticeship Patterns offers an inspiring and thought-provoking perspective on how to approach software development as a lifelong craft. It reinforced my belief that learning should be intentional and reflective, and it pushed me to think about how I can structure my growth more effectively. While I don’t entirely agree with every aspect of the apprenticeship model, I appreciate the book’s emphasis on continuous improvement, humility, and the importance of deliberate practice.

For aspiring and experienced developers alike, this book serves as a guide to not just writing better code, but becoming a better craftsman in the art of software development.

From the blog Discoveries in CS world by mgl1990 and used with permission of the author. All other rights reserved by the author.

How LibreFoodPantry and Thea’s Pantry Are Changing the Way to Support the Community

In today’s digital world, even food pantries are using technology to make a bigger impact. Two examples of this innovative approach are LibreFoodPantry and Thea’s Pantry. This is working in unique way to make food distribution more efficient and accessible, but  has its own twist on how to better serve those in need.

One thing that really caught my attention about LibreFoodPantry is how they use free and open-source software to support food pantries. What makes this so interesting is that food pantries typically operate on tight budgets, and paying for expensive software can be a huge strain. By using open-source software, LibreFoodPantry allows pantries to save money and focus more on helping people rather than dealing with costly tech tools. The software is easy to use, which means volunteers can spend more time providing food and less time trying to figure out complicated systems.

What makes this even better is the sense of community that LibreFoodPantry fosters. They encourage food pantries to work together and share ideas, which helps everyone improve. Volunteers and pantry staff can also get involved in shaping the software itself, making sure it fits the real needs of the people using it. This approach helps create a more connected and effective network of food pantries, which ultimately benefits those who rely on them.

On the other hand, Thea’s Pantry takes a slightly different but just as powerful approach. While Thea’s Pantry also provides food, what stood out to me is how they go beyond just feeding people. They offer additional support services like medical and educational resources, helping people address the many challenges they face, not just hunger. This holistic approach makes sure that individuals are supported in multiple areas of their lives, improving their overall well-being.

What I really love about Thea’s Pantry is how they look at the bigger picture. They understand that food insecurity is often linked to other problems like health issues or lack of access to education. By providing more than just food, they help people get back on their feet in a more comprehensive way.

Both LibreFoodPantry and Thea’s Pantry are doing incredible work, each in their own way. LibreFoodPantry uses technology to make food distribution easier and more efficient, while Thea’s Pantry offers a well-rounded approach that supports people in more areas of their lives. Together, they’re showing us new, more effective ways to help those in need.

From the blog Discoveries in CS world by mgl1990 and used with permission of the author. All other rights reserved by the author.

Introduction to REST APIs: A Beginner’s Insight

REST (Representational State Transfer) APIs have become a cornerstone in modern software development, enabling seamless communication between different systems. For those new to the field, understanding REST APIs is essential as it forms the foundation for integrating various services and building scalable applications. The blog post “Rest API Tutorial — A Complete Beginner’s Guide” from Moesif provides an excellent introduction to this topic. Here, I will summarize the content of the blog, explain why I selected this resource, and reflect on what I learned from it.

Summary of the Blog Post

The Moesif blog post starts by explaining what an API (Application Programming Interface) is and introduces REST as an architectural style for designing networked applications. It highlights that RESTful APIs are stateless, meaning each request from a client to a server must contain all the information the server needs to fulfill it. The post further discusses key concepts such as HTTP methods (GET, POST, PUT, DELETE), status codes, and the importance of endpoints in API structure.

The guide provides practical examples to illustrate these concepts, making it easier for beginners to grasp. It also touches on best practices, such as the use of proper status codes to indicate request outcomes and keeping URLs clean and intuitive. The post ends by emphasizing the importance of good documentation and consistent API versioning to ensure ease of use and maintainability.

Why I Selected This Resource

I chose this particular blog post because of its comprehensive yet beginner-friendly approach. As a computer science student, I am currently learning about software architecture and development practices. This guide stood out for its clarity in explaining complex concepts and its practical examples, which help bridge the gap between theory and real-world application. I wanted to understand REST APIs better, not just from a theoretical standpoint but in a way that I could apply in future projects, making this resource ideal.

Reflections on the Content

Reading through the blog post was eye-opening. It clarified the purpose and usage of REST APIs and reinforced my understanding of HTTP methods and status codes. The emphasis on statelessness and how each request must be self-sufficient was particularly insightful, as I previously struggled with this concept. Additionally, I learned the significance of designing intuitive endpoints and properly using status codes to indicate different outcomes, such as 200 for success or 404 for not found.

This resource has given me the confidence to start building simple RESTful APIs. I now appreciate why good API documentation and versioning are critical — they help developers maintain and scale services effectively. Moving forward, I intend to apply this knowledge in my coursework and future software projects, ensuring that the APIs I develop are well-structured, easy to use, and maintainable.

Conclusion

Overall, the “Rest API Tutorial — A Complete Beginner’s Guide” was a valuable resource that provided me with a solid foundation in RESTful API development. I highly recommend it to any beginner looking to understand how APIs work and how to implement them in practical projects. For those interested, you can read the full post here.

From the blog Discoveries in CS world by mgl1990 and used with permission of the author. All other rights reserved by the author.

Exploring REST API Calls

In the realm of web development, the importance of REST (Representational State Transfer) APIs cannot be overstated. They serve as the backbone of communication between client and server applications, facilitating the seamless exchange of data. My recent exploration of the article “Understanding REST APIs: A Comprehensive Guide” on Medium provided a deep dive into the intricacies of RESTful architecture, the principles behind it, and practical examples of its implementation.

I chose this article because it offers a holistic view of REST APIs, making it suitable for both beginners and seasoned developers looking to refine their understanding. The author does a commendable job of breaking down complex concepts into digestible sections, ensuring readers can follow along easily. The article not only covers the technical aspects of REST APIs but also emphasizes best practices and common pitfalls, which are crucial for anyone working with APIs.

One of the key takeaways from the article was the emphasis on statelessness in REST. Each API call is independent; the server does not store any client context between requests. This design choice simplifies scalability and reliability, allowing systems to handle multiple requests without the overhead of session management. Understanding this principle has reshaped my approach to API design. I now recognize the importance of making each API call self-contained and meaningful.

Additionally, the article highlighted the significance of HTTP methods—GET, POST, PUT, DELETE—and their respective roles in interacting with resources. This reinforced my understanding of how to use these methods appropriately to perform CRUD (Create, Read, Update, Delete) operations effectively. The practical examples provided illustrated how to structure requests and handle responses, making the learning experience both informative and applicable.

This material significantly impacted my perspective on API integration in my projects. Previously, I approached APIs with a surface-level understanding, often overlooking essential details that could enhance my applications. Now, I feel equipped to design and implement more robust and efficient RESTful services. In my future practice, I plan to apply these principles not just in personal projects but also in collaborative environments, where clear communication with APIs is crucial for successful integration.

In conclusion, “Understanding REST APIs: A Comprehensive Guide” served as an invaluable resource that deepened my understanding of RESTful architecture. The insights gained will undoubtedly influence my future work as I continue to navigate the complex world of web development and API integration.

For more details, you can read the article here: Understanding REST APIs: A Comprehensive Guide.

From the blog Discoveries in CS world by mgl1990 and used with permission of the author. All other rights reserved by the author.

Exploring Design Patterns in Computer Science: A Beginner’s Perspective

Design patterns are essential concepts in software engineering, providing time-tested solutions to common problems. As an apprentice in computer science, understanding design patterns can significantly boost your coding efficiency and software design skills. During my learning journey, I found an insightful article, Java Design Patterns from GeeksforGeeks, that provided me with a solid foundation on design patterns. Here’s a summary of the article and my reflections on how it has shaped my learning experience.

Summary of the Selected Article

The GeeksforGeeks article Java Design Patterns covers the key design patterns used in Java programming. It introduces three main types of design patterns—Creational, Structural, and Behavioral. Each category is explored with practical examples and explanations that break down the complexities of design patterns into digestible information. The article also touches on popular patterns like Singleton, Factory, Decorator, and Observer, providing clear definitions and illustrating their use cases in real-world Java applications. It serves as an excellent resource for beginners to grasp how design patterns can improve code readability, reusability, and maintainability.

Reason for Choosing this Resource

I chose this article because GeeksforGeeks is known for delivering educational content tailored to both novices and experienced developers. I needed a source that could present design patterns clearly and practically, specifically for Java programming, which I am currently studying. The website’s step-by-step approach to explaining concepts, accompanied by code snippets, resonated with my learning style. As a beginner, I was looking for a resource that could demystify design patterns without overwhelming me with technical jargon, and this article did exactly that.

Personal Reflection and Key Takeaways

The material was enlightening, especially in how it framed design patterns as reusable solutions to software design issues. Before reading the article, my understanding of patterns like Singleton or Factory was limited to theoretical concepts, but the examples provided helped me visualize their practical applications. One major lesson I took from this article is the importance of the Singleton pattern, which ensures that a class has only one instance and provides a global point of access to that instance. This concept is essential in areas like database connections, where having multiple instances could lead to conflicts.

Additionally, learning about the Factory pattern—a creational pattern that allows for the creation of objects without specifying the exact class—opened my eyes to how flexibility and scalability are achievable in code. This pattern is especially helpful when dealing with large projects where new object types might frequently need to be added.

The article not only strengthened my grasp of object-oriented principles but also inspired me to think more critically about how I structure my code. It shifted my perspective from merely getting the code to work, to considering how to design it efficiently for future use and maintenance. I now see design patterns as a roadmap to writing better, more scalable code.

Future Application of Design Patterns

Moving forward, I plan to incorporate these design patterns into my coding work practices, particularly in my Java projects. The Singleton pattern will be useful in managing system-wide resources, while the Factory pattern will aid in developing modular code that can easily evolve. Understanding these patterns equips me to write code that is not only functional but also adaptable, which is crucial as I delve into larger, more complex projects.

In conclusion, design patterns are invaluable tools for every software developer. Thanks to resources like the GeeksforGeeks article, I now have a clearer understanding of how to implement these patterns in Java, and I look forward to applying them in my future projects.

From the blog Discoveries in CS world by mgl1990 and used with permission of the author. All other rights reserved by the author.

Understanding Design Smells and Technical Debt: A Beginner’s Guide

In the world of computer science, especially for those new to programming, concepts like design smells and technical debt can seem daunting. However, grasping these ideas is crucial for building sustainable software. Design smells are indicators of potential problems in your code, such as overly complex structures or poor naming conventions. Technical debt, on the other hand, refers to the compromises made during the development process that can lead to greater issues down the line, akin to borrowing money that needs to be paid back later.

I recently came across the article “Understanding Technical Debt” by Tom Smith on Medium. This piece breaks down these concepts in an approachable manner, making them easier to understand for beginners. Smith discusses common design smells, such as “Long Method” and “Feature Envy,” and explains how they can accumulate into technical debt if ignored.

I chose this article because I believe it provides a solid foundation for understanding these concepts without overwhelming beginners with jargon. As I embark on my journey in computer science, I find it essential to learn about the long-term implications of my coding decisions. Smith’s article highlights the importance of recognizing design smells early on, which resonated with me as I often focus on getting things done rather than considering the quality of my code.

What I learned from the article is that design smells serve as early warning signs. For example, if a method is too long or complex, it may indicate that it’s doing too much and should be broken down into smaller, more manageable pieces. This insight has made me reflect on my past coding experiences, particularly a group project where we rushed to implement features without thoroughly reviewing our code. The result was a project that became difficult to manage and understand. I realized that by overlooking design smells, we inadvertently added technical debt to our project.

Moving forward, I plan to apply this knowledge in my coding practice by adopting a more mindful approach. I want to prioritize code quality and regularly check for design smells as part of my workflow. Implementing practices like peer code reviews and refactoring sessions will help ensure that my code remains clean and maintainable. I believe this proactive approach will not only enhance my skills but also contribute to a more positive team environment where everyone is encouraged to uphold coding standards.

In conclusion, understanding design smells and technical debt is vital for anyone starting in computer science. By paying attention to these indicators, we can write better, more maintainable code. I highly recommend reading Tom Smith’s article for a beginner-friendly introduction to these essential concepts.

Resource:
* Fowler, M. (n.d.). Technical Debt and Design Smells: A Practical Guide. Retrieved from Martin Fowler’s website.

* Smith, T. (n.d.). Understanding Technical Debt. Medium. Retrieved from Medium.

From the blog Discoveries in CS world by mgl1990 and used with permission of the author. All other rights reserved by the author.

Welcome to Software Construction, Des & Architecture blog.

In this blog will be talking about the aspects of software construction, design and architecture aspects.

When building software, three important aspects to consider are construction, design, and architecture. Construction is about writing the actual code that makes the software work. It’s like putting together the pieces of a puzzle to ensure everything fits and functions correctly. Design is like planning the layout of a house before you start building. It involves figuring out how different parts of the software will work together, making sure everything is organized and easy to use.

Architecture is the big-picture plan for the software, similar to designing the overall structure of a building. It decides how all the different pieces fit together and interact with each other. Good architecture ensures the software can handle changes and grow over time without falling apart. By focusing on construction, design, and architecture, developers can create software that’s not only functional but also easy to maintain and expand in the future.

From the blog Discoveries in CS world by mgl1990 and used with permission of the author. All other rights reserved by the author.

Increasing Code Fortification: A Guide to Security Testing in JUnit 5

In the ever-evolving landscape of software development, ensuring robust security measures has become paramount. With the increasing frequency and sophistication of cyber threats, developers must incorporate stringent security testing protocols into their workflows to fortify their code against potential vulnerabilities. One such indispensable tool in the developer’s arsenal is JUnit 5, a powerful testing framework for Java. In this blog post, we delve into the realm of security testing in JUnit 5, exploring its significance, methodologies, and best practices.

Understanding Security Testing in JUnit 5

Security testing in JUnit 5 involves the systematic examination of code to identify and rectify security vulnerabilities. Unlike traditional testing, which primarily focuses on functional correctness, security testing scrutinizes the codebase for potential exploits and weaknesses that could be exploited by malicious actors.

Methodologies for Security Testing in JUnit 5

  1. Static Code Analysis: Static code analysis tools such as FindBugs and SonarQube play a pivotal role in identifying security vulnerabilities in the codebase even before execution. By analyzing the code’s structure and logic, these tools can flag potential security loopholes, ranging from injection vulnerabilities to insecure data handling practices.
  2. Input Validation Testing: Input validation is a crucial aspect of security testing, especially in web applications susceptible to injection attacks. In JUnit 5, developers can write test cases to simulate various input scenarios, ensuring that the application robustly validates user inputs to prevent injection attacks like SQL injection and cross-site scripting (XSS).
  3. Authentication and Authorization Testing: Authentication and authorization mechanisms are integral components of secure software systems. JUnit 5 facilitates the creation of test suites to evaluate the effectiveness of authentication mechanisms, ensuring that only authorized users can access sensitive functionalities and resources.
  4. Security Configuration Testing: JUnit 5 allows developers to test security configurations, such as HTTPS settings, encryption algorithms, and access control policies. By meticulously examining these configurations through test cases, developers can identify misconfigurations and strengthen the overall security posture of the application.

Best Practices for Security Testing in JUnit 5

  1. Comprehensive Test Coverage: Aim for comprehensive test coverage to ensure that all critical components and functionalities are thoroughly evaluated for security vulnerabilities.
  2. Regular Regression Testing: Incorporate security tests into your regression testing suite to detect regressions that could reintroduce previously patched vulnerabilities.
  3. Utilize Mocking and Stubbing: Leverage mocking frameworks like Mockito to simulate external dependencies and stub out sensitive operations, allowing for isolated and controlled security testing scenarios.
  4. Continuous Integration and Delivery (CI/CD): Integrate security tests into your CI/CD pipeline to automate the testing process and identify vulnerabilities early in the development lifecycle.

Conclusion

Security testing in JUnit 5 is an indispensable practice for safeguarding software applications against malicious threats. By employing rigorous testing methodologies and adhering to best practices, developers can bolster the security posture of their codebases, thereby mitigating the risks associated with cyber attacks. Embrace security testing as an integral part of your development workflow, and fortify your code against potential vulnerabilities.

For further insights into security testing in JUnit 5, explore the official JUnit 5 documentation here. Additionally, delve into static code analysis tools such as FindBugs here and SonarQube here.

From the blog Discoveries in CS world by mgl1990 and used with permission of the author. All other rights reserved by the author.

Exploring Testing Techniques.

Testing is an essential aspect of software development, ensuring that our applications meet quality standards and perform as expected. However, the world of testing can be vast and intricate, with various techniques and methodologies to choose from. In this guide, we will delve into six key testing approaches: Pairwise, Combinatorial, Mutation, Fuzzing, Stochastic, and Property-Based Testing.

Pairwise Testing:

Pairwise testing, also known as all-pairs testing, is a method used to test the interactions between pairs of input parameters. By selecting a minimal set of test cases that cover all possible combinations of pairs, this technique efficiently identifies defects without exhaustive testing. It’s particularly useful when dealing with large input domains. For more information, you can explore Software Testing Fundamentals.

Combinatorial Testing:

Combinatorial testing extends pairwise testing by considering interactions among multiple parameters simultaneously. Instead of testing every possible combination, it focuses on covering a representative subset of combinations. This approach helps in reducing the number of test cases required while still providing comprehensive coverage. Learn more at National Institute of Standards and Technology (NIST).

Mutation Testing:

Mutation testing involves making small modifications (mutations) to the source code and running test cases to check if these mutations are detected. It assesses the effectiveness of test suites by measuring their ability to detect changes in the code. By simulating faults in the program, mutation testing helps in identifying weaknesses in test cases. You can find further insights at Striker.

Fuzzing:

Fuzz testing, or fuzzing, is a technique where inputs are fed into a system in an automated and randomized manner, often with invalid, unexpected, or malformed data. The goal is to uncover vulnerabilities such as crashes, memory leaks, or security flaws that may not be apparent under normal testing conditions. To explore more about fuzzing, visit OWASP.

Stochastic Testing:

Stochastic testing involves using random or probabilistic techniques to generate test cases. Unlike deterministic testing, where inputs are predefined, stochastic testing introduces variability, mimicking real-world scenarios. It’s particularly useful in systems where inputs are inherently unpredictable or when exhaustive testing is impractical. Dive deeper into stochastic testing at Investopedia.

Property-Based Testing:

Property-based testing focuses on defining properties or specifications that the system should satisfy and then generating test cases automatically to verify these properties. Instead of specifying individual test cases, developers define general rules, and the testing framework generates inputs to validate these rules. Learn more about property-based testing from Medium.

In conclusion, understanding different testing techniques empowers software developers and testers to choose the most appropriate methods for their projects. Whether it’s ensuring thorough coverage, detecting defects, or improving resilience, these approaches play a crucial role in delivering high-quality software products.

From the blog Discoveries in CS world by mgl1990 and used with permission of the author. All other rights reserved by the author.