Category Archives: CS@Worcester

Unveiling Behavior-Driven Development: A Fresh Perspective (Week-10)

In the fast-paced realm of software development, Behavior-Driven Development (BDD) emerges as a transformative approach, promoting communication and precision in building software that aligns with user expectations and business objectives. Unlike traditional development methodologies, BDD emphasizes the behaviors of software under various conditions, prioritizing user needs and ensuring a shared understanding among all stakeholders.

At its core, BDD focuses on defining expected software behaviors through readable and understandable scenarios. This collaborative process involves all stakeholders, including developers, testers, and non-technical personnel, facilitating a common language and shared vision for the project. These scenarios, structured in a Given-When-Then format, not only guide the development and testing processes but also serve as living documentation and a source of truth throughout the project lifecycle.

The integration of BDD into a development process begins with the identification of user stories, which describe the needs and goals of the end user. These stories are further broken down into specific scenarios, outlining how the software should behave in different situations. This meticulous approach ensures that every feature developed is directly tied to user requirements, reducing unnecessary work and focusing efforts on delivering value.

BDD’s strength lies in its ability to bridge the communication gap between technical and non-technical team members. By translating technical specifications into a language accessible to all, BDD ensures that everyone has a clear understanding of what is being built and why. This alignment leads to more accurate product outcomes and a smoother development process.

Furthermore, BDD enhances the quality of the final product. Automated tests derived from behavior scenarios ensure that all functionalities meet the predefined criteria, reducing the likelihood of bugs and regressions. This continuous validation not only boosts product reliability but also instills confidence among the team and stakeholders.

However, the transition to BDD requires a cultural shift within the organization. It demands active participation from all parties involved and a commitment to ongoing collaboration and communication. While this can be challenging, the long-term benefits of improved clarity, better product quality, and increased stakeholder satisfaction are invaluable.

In conclusion, Behavior-Driven Development offers a systematic and collaborative approach to software development, centered around clear communication and a deep understanding of user needs. By adopting BDD, teams can build software that not only meets but exceeds user expectations, fostering a more efficient and effective development process. As the digital landscape continues to evolve, methodologies like BDD will play a crucial role in shaping the future of software development, ensuring products are not only functional but also truly aligned with the needs and goals of the users they serve.

Additionally, Lambdatest offers insights into the intricacies of BDD, discussing its limitations and providing best practices. This resource parallels BDD to planning a perfect party, emphasizing the importance of teamwork, early error detection, and ensuring every part of the product is right.
https://www.lambdatest.com/learning-hub/behavior-driven-development

From the blog CS@Worcester – Kadriu's Blog by Arber Kadriu and used with permission of the author. All other rights reserved by the author.

“Sweep the Floor”: Embracing Humility in Professional Growth

Summary of the Pattern: “Sweep the Floor” addresses the importance of humility and willingness to tackle basic, sometimes menial tasks in professional environments, especially for newcomers. This pattern suggests that by taking on simple, essential tasks that others may overlook or avoid, individuals can demonstrate their dedication, learn the intricacies of their environment, and gradually earn the trust and respect of their colleagues. It emphasizes that such tasks, though seemingly minor, play a crucial role in team dynamics and project success.

My Reaction: The principle of “Sweep the Floor” resonated with me immediately, highlighting an often-underappreciated aspect of professional life: the value of humility. In a culture that frequently celebrates only the most visible successes, this pattern serves as a refreshing reminder of the significance of foundational work. It speaks to the idea that every contribution, no matter how small it may seem, is vital to the collective effort and that recognition and respect are earned through consistent, reliable participation in all aspects of work.

Insights and Changes in Perspective: Reflecting on this pattern prompted me to reconsider my approach to team contributions and the opportunities to demonstrate value and build relationships through seemingly simple tasks. It has encouraged me to actively seek out and embrace these opportunities, recognizing them as stepping stones to deeper understanding and integration within a team. This perspective shift has not only made me more open to various forms of participation but has also deepened my appreciation for the complexities of teamwork and project management.

Disagreements and Critiques: One potential critique of “Sweep the Floor” could be that it risks reinforcing a hierarchical or outdated view of work, where newcomers are expected to prove themselves through less desirable tasks. However, I view this pattern not as a reinforcement of hierarchy but as an acknowledgment of the communal aspect of work, where every task, regardless of its perceived status, contributes to the greater goal. It’s crucial, though, to ensure that this principle is applied with fairness and does not exploit or undervalue anyone’s contributions.

Conclusion: “Sweep the Floor” has profoundly impacted my understanding of teamwork and professional development. It serves as a powerful reminder that humility, eagerness to contribute in any capacity, and recognition of the value in all tasks are essential qualities for personal growth and team cohesion. As I move forward in my career, I am inspired to apply this pattern, understanding that every action, no matter how small, can lead to significant impacts and lasting relationships within any professional setting.

From the blog CS@Worcester – Abe's Programming Blog by Abraham Passmore and used with permission of the author. All other rights reserved by the author.

Understanding Software Test Doubles

Dummies, Stubs, Spies, Fakes, and Mocks

Software testing is a crucial component of the software development lifecycle, ensuring that your application functions correctly and meets user expectations. One of the key concepts in unit testing is the use of test doubles, which help isolate the system under test (SUT) by replacing its dependencies. This isolation is essential for creating effective and reliable unit tests. In this blog, we will delve into the different types of test doubles: Dummy, Stub, Spy, Fake, and Mock, and explain their roles and usage with examples.

Dummy Objects

A Dummy object is the simplest form of a test double. Its sole purpose is to fill parameter lists without actually being used in the test itself. Typically, a Dummy can be a null object or an instance with no real logic, used just to satisfy method signature requirements. For instance, when testing a method that requires an interface which the test doesn’t interact with, you could pass a Dummy implementation of this interface. However, a Dummy should never affect the test outcome.

Example:

In this example, dummyBoard is a Dummy since the test does not interact with it beyond instantiation.

Fake Objects

Fakes are more sophisticated than Dummies. They have working implementations, but usually take shortcuts and are simplified versions of production code. Fakes are particularly useful when testing interactions with external resources, like databases. Instead of connecting to a real database, you can use a Fake object that simulates database operations.

Example:

Stubs

Stubs provide canned answers to calls made during the test, usually not responding to anything outside what’s programmed in for the test. They are used to supply the SUT with indirect input to test specific scenarios.

Example:

Mock Objects

Mocks are used to verify interactions between the SUT and its dependencies. They can assert that objects interact with each other in the right way, making them a powerful tool for behavior verification.

Example:

In this case, mock is used to ensure that the Module correctly logs messages when an exception is thrown.

Spy Objects

Spies are similar to Mocks but are used for recording information about how they were called. They can be used for more complex scenarios where you need to assert that certain methods were called a specific number of times or with certain parameters.

Example:

Here, spyLogger acts as a Spy, recording the number of times Log was called.

Understanding the differences between Dummies, Fakes, Stubs, Mocks, and Spies and when to use each can significantly enhance your unit testing strategy, leading to more maintainable and robust code. While these tools offer great flexibility, remember that the ultimate goal is to write clear, concise, and reliable unit tests that effectively cover your code’s functionality.

https://dipakgawade.medium.com/mocking-for-unit-tests-understand-the-concept-221b44f91cd

From the blog CS@Worcester – Coding by asejdi and used with permission of the author. All other rights reserved by the author.

Mocks and Stubs

Testing is an important part of coding, and software development. Sometimes though, testing can be tedious work, and creating tests that work properly according to your code can be difficult. This should be the case anyways, as testing is a key aspect to software development, but what if you could do this process a bit more quickly. Creating mocks and stubs can be a good alternative, especially if multiple people are working on different parts of the same project or software. 

In this blog post, June Jung touches upon mock and stub testing. They describe mock testing as “creating a fake version of an external or internal service that can stand in for the real one,” and stub testing as “creating a stand-in, but a stub only mocks the behavior, but not the entire object.” The whole idea of mocks and stubs is to create a fake or a stand-in that does not do anything. This may seem strange, having completely useless methods and functions, but the thing we want to test for is the interactions between the methods and functions. Seeing whether or not they return the correct return values, call the correct methods, etc. This will reduce the amount of time needed to test the functions, compared to testing full, complete functions and methods. Jung says that by using mocks and stubs, you can “reproduce more complex scenarios more easily. For instance, it is much easier to test the many error responses you might get from the filesystem than to actually create the condition.” Jung says this specifically for unit + component testing, but this principle can apply for any kind of testing. In fact, they touch upon multiple cases where mocks and stubs can be used, such as internal functions, integration testing, and contract-based testing. They also provide code examples, and graphs to help you visualize the concept, which can be helpful.

Jung says that as your code grows, your tests should as well, meaning you shouldn’t continue to use the same tests as you continue to write more code, losing the mocks and the stubs. That being said, they’re good to help start, providing a base to continue with. Jung’s blog post is a good resource, as they also have linked another post that goes into the difference between mocks and stubs. It also appears that their blog post is part of multiple posts, which may be worth looking at for more information.

From the blog CS@Worcester – Cao's Thoughts by antcao and used with permission of the author. All other rights reserved by the author.

Mastering Object-Oriented Testing: Ensuring Robust OO Software Design (Week-10)

Object-oriented testing (OOT) plays a critical role in verifying the functionality and robustness of object-oriented software systems. This form of testing addresses the unique challenges introduced by OO principles such as encapsulation, inheritance, and polymorphism. In this guide, we delve into the essential phases of OOT, including class testing, integration testing, system testing, and the utilization of Unified Modeling Language (UML) diagrams, to ensure the development of reliable OO applications.

Class Testing: The Cornerstone of OOT

Class testing is the first step in the OOT process, akin to unit testing in procedural programming. This stage focuses on the smallest units of OO design – the classes. It involves:

  1. State-based Testing: Assessing objects in different states to ensure they behave correctly under various scenarios.
  2. Method Testing: Verifying the functionality of each method within a class, considering diverse input combinations and their effects.
  3. Attribute Testing: Ensuring that class attributes maintain valid states throughout the object’s lifecycle.

Thorough class testing is fundamental, as it lays a solid foundation for more complex stages of testing, facilitating early detection and correction of defects.

Integration Testing: Bridging the Classes

Integration testing in OOT checks class interactions, vital for managing OO systems’ complex dependencies. Key approaches include:

  1. Collaboration Testing: Checks the data exchange and cooperation between objects to confirm correct combined operations.
  2. Sequence Testing: Focuses on the order of method calls and message passing among objects, ensuring they align with the desired workflows.
  3. Subsystem Testing: Involves testing groups of related classes, or subsystems, to identify any integration mishaps early on.

Effective integration testing ensures that individual classes operate harmoniously within the larger system context.

System Testing: Validating the Entire Application

System testing evaluates the complete OO software against specified requirements to ensure it meets its intended purposes. This encompasses:

  1. Use Case Testing: Derives test cases from use cases, ensuring the system fulfills user expectations and business needs.
  2. Scenario Testing: Simulates real-world scenarios to uncover any unexpected system behaviors or failures.
  3. State Transition Testing: Assesses the system’s responses during various state changes, guaranteeing consistency and reliability.

This holistic approach verifies the system’s overall functionality and user readiness.

Utilizing UML Diagrams for Insightful Testing

UML diagrams are invaluable in OOT for visualizing the structure and dynamics of OO systems. They aid testers and developers by providing a clear representation of classes, interactions, and system states, facilitating the creation of targeted and effective test cases.

Conclusion: Elevating Software Quality with Object-Oriented Testing

Object-oriented testing is indispensable for crafting high-quality OO software. By systematically conducting class testing, integration testing, and system testing, and leveraging UML diagrams for enhanced insight, developers can address the complexities of OO systems effectively. A recommended resource for those seeking to deepen their understanding of OOT practices is “Testing Object-Oriented Systems: Models, Patterns, and Tools” by Robert V. Binder. Implementing these strategies ensures the delivery of robust, user-centric OO applications that stand the test of time.

From the blog CS@Worcester – Kadriu's Blog by Arber Kadriu and used with permission of the author. All other rights reserved by the author.

sweep the floor

When you first get placed on a team, it’s sometimes hard to get your bearings if you aren’t given an explicit task to work on to begin with. We sort of experienced this at the start of the semester, where we weren’t all too familiar with the Thea’s Pantry project even after working with forks of it for assignments in prior courses. Part of this is just the nature of working with something new, and having the expectation of providing value to it in a practical sense.

In this way, it makes sense the way we approached the issues that we took for the first sprint. For the most part, these issues were fairly simple and mostly plumbing, which can also be classified as sweeping the floor. The idea for sweeping the floor is that you take simple tasks that, while necessary, aren’t all that interesting, in order to build confidence in yourself with the project and build rapport with the team.

The authors make a good point in that it might not feel great to do as someone with a Computer Science degree that you worked hard for, but the reality is that the degree is really just a way to get your foot in the door. Same with any other way that you gained the qualifications to get accepted for a job or project that you’re working on. The real work is the work you do when you’re placed into a project, where you really get to apply the basics that you learned in college while also learning more practical skills.

I really think this is a good approach to take when you feel out of your element in a new environment. Maybe you just got hired for your first internship or even first full-time job, and while you are excited, you don’t really know how to actually provide value to the project, because you haven’t necessarily had that sort of experience before. This seems really helpful to get your bearings in a new project. The authors do mention a couple drawbacks to this approach, with the most notable one being the feeling of being stuck doing the small tasks without branching out due to anxiety, but there are ways out of this mindset too.

From the blog CS@Worcester – V's CompSCi Blog by V and used with permission of the author. All other rights reserved by the author.

Week 9 Blog Post

Choosing a topic for this week I tried to find something we had recently touched upon. Last week we went over mocking and expanding my knowledge of this topic can benefit me and the class. Searching for articles about mocking I stumbled upon one that shares the negatives of using mocking data. To counter-attack the ideas we learned in class it is always great to know both sides to using a concept. 

This article doesn’t fully dispose of mocking but gives ideas when it’s good to use. It gives a variety of examples including “Isolating the unit under test from other components or dependencies that are not relevant to the test, Speeding up the test execution by avoiding network calls or database queries that can be slow or unreliable, and Controlling the test input and output by creating predictable and consistent data that can be easily verified”. These ideas are then counterposed to the negatives such as “Introducing errors or inconsistencies between the mock data and the real data, which can lead to false positives or false negatives in the test results, Reducing the coverage and confidence of the test, by not testing the actual behavior and logic of the external source or the interaction with it, and Increasing the maintenance and complexity of the test, by requiring extra code and logic to create and manage the mock data”. The flaws of mocking data are mainly it does not use real data making it much more different from the real data creating disparities between the two. These tests ignore scenarios with much more complexity and these error and bugs can go unseen. The author assures the reader to use a data source to improve the tests.

After reading this article it gave me insight into the negatives of using mocking. The week prior activities made the use of mocking reduce time in creating classes but it’s good to know when it should be used and when it shouldn’t. I wish there was a perfect solution for every test but to find bugs in your code you must expand your horizon. Reading this article made me see that a variety of tests testing different things can overall benefit you. You never have to completely ignore a type of test but being able to see the positives and negatives can save you in the long run. Plus it will allow you to have a broader knowledge knowing that this may have flaws but there are things I can add to have a satisfactory end product.       

https://medium.com/@queenskisivuli/why-mocking-data-is-a-bad-practice-for-testing-a20d2d7104aa

From the blog CS@Worcester – DCO by dcastillo360 and used with permission of the author. All other rights reserved by the author.

Unit Testing

This week I decided to discuss Unit testing because although we have finished a few activities on the subject, I would like to read up on it to get a better understanding of it. While searching for a blog to discuss, I found this blog called “Unit Testing Best Practices: 9 to Ensure You Do It Right” from Testim. This blog also discusses what a unit test is, why we write them, the benefits of unit testing, how to achieve testable code, who creates them, and the difference between unit testing and integration testing.

The text begins by explaining that unit tests focus on very small parts of the application in complete isolation and compare their actual behavior with the expected behavior. In this section, the idea of complete isolation is thoroughly explained with the idea that “you don’t typically connect your application with external dependencies”. This is what makes unit tests so fast and stable.

The next section explains why they are created in bullet points and have the main ideas bolded. This structuring is helpful to simplify the ideas for the reader and make sure that the main ideas stick out for them. These were the bolded parts of the bullet points in the section: unit tests help you find and fix bugs earlier, your suite of unit tests becomes a safety net for developers, unit tests can contribute to higher code quality, unit tests might contribute to better application architecture, unit tests can act as documentation, and detect code smells in your codebase. I think a lot of the ideas presented were easy to comprehend based on the bolded part but I had to read more about the last bullet point because the term” code smells”(signs that something is wrong with your code ) was not obvious to me. 

The section that explained the difference between integration testing and unit testing was fairly short because they narrowed the main idea down to a few sentences: “It’s all about the level of isolation. While unit tests have to be completely isolated, integration tests don’t shy away from using external dependencies….integration tests offer a more high-level view of the application than unit tests do. Because of that, the feedback they provide is both more realistic and less focused.”

The 9 best practices at the end are titled: Tests Should Be Fast, Tests Should Be Simple, Test Shouldn’t Duplicate Implementation Logic, Tests Should Be Readable, Tests Should Be Deterministic, Make Sure They’re Part of the Build Process, Distinguish Between The Many Types of Test Doubles and Use Them Appropriately, Adopt a Sound Naming Convention for Your Tests, and Don’t Couple Your Tests With Implementation Details. These tips are easy to understand based off of the title alone but throughout each section, the author uses bits of code as examples and bullet points to thoroughly explain each idea. In the future, I will refer to these tips when I need to write tests for a project I will work on.

From the blog CS@Worcester – Live Laugh Code by Shamarah Ramirez and used with permission of the author. All other rights reserved by the author.

Stay in the Trenches

This week I decided to discuss the pattern called “Stay in the Trenches”. In this section, the problem presented is where you are offered a promotion into a role that will pull you away from programming. It mentions that this offer is an illusion of accomplishment that will test your sustainable motivation and determination to walk the long road.  I decided to pick this pattern because it involves the idea of sustainable motivations which is a pattern I wrote about previously. I am unsure about what is motivating me to stay in the field so I like thinking about these kinds of topics. I don’t think this section has really changed my mind about the way I think about my profession though.

Many people equate a promotion with success but in the problem presented (a promotion that would pull you away from programming), you will be trading the programming skills that you have worked to develop for said promotion. The tet calls for you to stay on your path and work with your manager to find other mechanisms to reward you for your excellent work. This means if your company refuses to be flexible, you should find opportunities somewhere else. 

I agree that it would be best to continue on the path of software engineering since you’ve dedicated a lot of time in an attempt to become a master but simply saying that if your organization is inflexible then you should find opportunities elsewhere is a bit easier said than done. I think you can love this path but if life knocks you down it may be a bit difficult to stay on the path. If you are able to find other opportunities, that’s great; you can continue on the path. If you have trouble finding other opportunities and you need the resources that the promotion can provide, then you may just have to take that promotion. I’m not saying that you have to give up software engineering forever, but you might have to take a little detour and stray from the path a little at least until you can find other opportunities elsewhere. You can still love software engineering and pick up projects in your free time but sometimes you have to be realistic in this society career wise. 

Lastly, I do think the list of possible alternate rewards for your excellence was great. It suggested to “consider whether there are standard constraints that could be loosened in your case” and to  “prepare a list of these alternative rewards so that when you reject that promotion, you’re in a position to negotiate based on a clear understanding of your own motivations”. I think those are very helpful suggestions.

From the blog CS@Worcester – Live Laugh Code by Shamarah Ramirez and used with permission of the author. All other rights reserved by the author.

A Deeper Dive into Mocking

In class, we began learning about the use of mocking in software testing. After doing an activity, I realized I only slightly understood the purpose of it. So, I decided to investigate, which is when I found The Art of Mocking by Gil Zilberfeld and Dror Helper.

The article begins by giving an introduction to unit tests for those who might not be familiar. They also give an example in C#, which is the language they use for the rest of the article. However, this does not impact information about mocking besides the syntax of the examples.

Once unit tests are covered, hand-rolled mock tests are introduced: they are classes that the developer(s) code which take the place of the real objects for testing purposes. It might not accurately test the system, but it ensures the business logic of the class works. 

The types of mocking listed are those manually made by the developers and those auto generated by mocking frameworks (Mockito or Moq). The article goes quite in depth into mocking frameworks, in their types, what they do, and what to look for when choosing one. Zilberfeld and Helper also discuss the benefits of mocking, which generally boils down to the fact that mocking cuts loose extra requirements for testing, such as databases and other external/complex resources.

Lastly, the best practices and potential hazards are listed. From what I gathered, the important ones were:

  • Only use fake objects when necessary, as too many can create weak/fragile tests
  • Understand what you’re testing and the dependency
  • At most two assertions/verifications per test

I selected this article because I was struggling a little bit with what mocking was and why it was useful. I had somewhat understood the concept and the idea behind it in class, but needed to go on a deeper dive to get a better grip on it. This resource also seems pretty real, in the sense of it feels homemade and focused; all the important stuff is in the articles themselves, not a subscription or anything. 

This article is superb with its examples and clear, in-depth explanations of unit tests and mocking. The formatting is easy to follow and allows for smooth learning and transitions from concept to concept. I personally believe that mocking is quite useful when applied lightly. I learned that Verify should only be used in fake objects when it’s the only way your program can pass or fail; otherwise, it might not matter whether every method actually calls the expected method. 

This affected me in a positive way as it gave me greater insight to mocking and more confidence in my personal understanding as to why we use it. I expect to apply this in a future job when I might need to test a method that uses database information, but it would take too many resources to use the database for testing purposes.

From the blog CS@Worcester – Josh's Coding Journey by joshuafife and used with permission of the author. All other rights reserved by the author.