Category Archives: CS@Worcester

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.

CS-448: Week 12

The Deep End

“The Deep End” pattern is about feeling unsatisfied with the path taken when learning new skills. The path taken has been small, safe steps that has made the learning process plateau. A way to jump start the learning process is by challenging yourself with bigger things such as bigger projects, working with larger teams, more complex projects, etc.

A solution to this pattern is to jump into the deep end, rather than waiting until you are ready. This is because the latter can lead to never starting anything, or challenging yourself to learn new skills. When a difficult problem occurs, rather than shying away, diving into the deep end and facing the problem head on is what will help in the long run. However there are some risks that are involved with going straight into the deep end. A risk is that you may get overwhelmed and fail. Although you may fail, failing is not necessarily a bad thing. Being prepared to fail, and recovering is what drives growth and provides opportunities that would be lost if the risk was never taken in the first place.

As mentioned before, in order to grow, bigger projects need to be made as a way to challenge yourself. Previous project’s size can be quantified by looking into those previous projects and marking down how many lines of code was written with how many developers. After reviewing all previous work, a chart can be made to see where how the next project compares.

Conclusion

I enjoyed reading about this pattern. I found the action to the pattern to be interesting because creating a chart, representing the size of your previous work, is something I would not have thought to do. However that process can be useful when determining if a project is at a large enough scale that can challenge previous projects. The pattern has changed the way I think about failure and taking risk. I like how the pattern paints the potential of failure as something that should be invited because I feel that failure is something that is not normally deemed acceptable. The pattern has ultimately changed the way I think about taking risks because risks and recovering from failures are what key to growth.

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

Mutation Testing

A topic we touched upon in class for a tiny bit was mutation testing. It is a different kind of software testing, where it alters your code and then runs your tests. If your tests fail, that means your tests are good. If your tests pass, that means your tests are not good. The altered versions of the code are called mutants, and if they are caught by the tests, as in failed, they are considered killed. If they pass, they are considered to have survived. The concept is strange, but can be effective, especially in finding inaccurate tests or seeing if you have enough tests.

In this blog post, Uncle Bob talks about his experience with mutation testing, how he came upon it, some benefits and how it works. He starts off by stating some issues with unit testing, such as writing enough tests, covering every line, branch, or path, and whether or not a test will fail depending on if you change some code. He answers these issues with sufficiency, coverage, and semantic stability, all of which can be solved by using mutation testing. It is fairly simple to run, and there is multiple ways to go about it. You run pitest tool, which alters your code a little bit, such as inverting if statements. It will do this more than once, where each variation of your code is a mutant. Then, for each mutant, it will run through all of your tests. If the tests fail, the mutant is killed, and if the tests pass, the mutant survived. Ideally, you want all of the tests to fail, which may be difficult to wrap your head around, typically you want your tests to pass. Having mutation testing is just another layer of testing to ensure your code is working properly. If a mutant survived, a number of things could have happened, such as ignored tests or discipline became too relaxed and people started writing sloppy code. Either way, it’s a good way to reinforce your tests and code. 

We did not really get to play around with this a lot in class, but it was cool to see how it worked. It had created multiple batches of mutants and might have ran the tests individually, but I may be wrong about that. If we had the chance to run it on code that we wrote, or if I had ran it on code that I wrote, maybe I could have understood it more. I will definitely use this in the future.

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

CS-443: Week 15

Performance Testing

Performance testing is the process of evaluating how a system performs under specific workloads. Responsiveness and stability of the system is monitored by examining the speed, reliability, and application size. Common indicators that are used for testing are network response times, number of users the system can handle at a time, processer memory consumption, and more.

Performance testing is an important part of the software development process. If an application is not tested before being released, users may have a negative experience because of errors that could have been found in the performance testing phase. Users that have a negative experience may be deterred from using the application in the future resulting in fewer overall users. Performance testing aims to find these errors before release, so users can have the best possible experience

When is performance testing done?

In software development, there are two main phases: development and deployment. Development testing focuses on individual components such as web services, APIs, and microservices. The earlier development testing begins, the earlier errors can be caught. Catching these errors early in the development phase is important because as the code base progresses, there is more and more code building on top of code that may have errors. This can make fixing the error more complicated. As the application becomes larger, comprehensiveness of the tests should also scale alongside. However, the application may get to a point where testing in the development phase becomes unreasonable and testing is done during the deployment phase. This happens when testing involves replicating a production environment, but recreating the environment is too difficult or expensive.

Types of Performance Testing

There are many types of performance testing that are done throughout the development process to verify the application performs as expected and can meet user requirements. Some of these performance testing types are:

  • Load Tests – Tests the application under a realistic load by simulating virtual users. Response times are monitored, which can reveal potential bottlenecks to the system’s performance.
  • Stress Tests – Similar to Load Tests, but the number of simulated virtual users is greatly increased. This is to see how the application runs when under peak activity.
  • Soak Tests – Tests are conducted over an extended amount of time, as opposed to the tests mentioned above. This test is to evaluate how the system performs when under intense loads for a prolonged amount of time.

Conclusion

This article was chosen because it covered a variety of topics within performance testing, so I was able to gain a general understanding of what performance testing is. Performance testing is an important process in software development because it finds potential weak spots in a system. These weak spots can come from slow response times during peak activity, long load times, etc. Therefore, performance testing should be done on all systems to improve the user experience. In the future, I intend to look further into performance testing tools and frameworks to see how I can implement them in later projects.

Resources:

https://www.tricentis.com/learn/performance-testing

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

The Strength in In-Depth Exploration

Pattern Summary:

The “Dig Deeper” pattern from “Apprenticeship Patterns” advises aspiring software craftsmen to explore their craft beyond surface-level understanding. It emphasizes the importance of curiosity, continuous learning, and seeking deeper insights into software development concepts, tools, and techniques.

Reaction to the Pattern:

Upon reading about the “Dig Deeper” pattern, I was immediately struck by its relevance and applicability to my journey as a software enthusiast. What stood out to me as particularly intriguing and valuable was the idea of embracing curiosity as a driving force for growth. This pattern encourages us to go beyond mere familiarity with programming languages or frameworks and delve into the underlying principles, design patterns, and best practices that shape our craft. It has sparked a renewed sense of curiosity and passion for exploring the depths of software development.

Impact on Professional Perspective:

The “Dig Deeper” pattern has had a profound impact on how I view my intended profession and approach learning. It has shifted my focus from superficial knowledge acquisition to a more profound understanding of core concepts and foundational principles. By digging deeper into software development topics, I’ve gained a deeper appreciation for the intricacies and complexities of the craft. This pattern has reshaped my learning strategies, prompting me to prioritize depth over breadth and invest time in mastering fundamental concepts.

Disagreements and Critiques:

While I wholeheartedly embrace the essence of “Dig Deeper,” one potential challenge I’ve encountered is the overwhelming volume of information available in the software development realm. It can be daunting to decide which areas to delve deeper into and how to manage the depth of exploration effectively. However, I’ve found that setting specific learning goals, leveraging resources like documentation, tutorials, and mentorship, and focusing on practical application have helped overcome this challenge.

Overall Reflection:

Embracing the “Dig Deeper” pattern has been a transformative experience in my professional development journey. It has fueled my curiosity, expanded my knowledge horizon, and enriched my problem-solving capabilities. By diving deeper into software development concepts, I’ve gained confidence, resilience, and a deeper sense of fulfillment in my craft. This pattern has instilled in me a lifelong commitment to continuous learning and mastery, shaping the way I approach challenges, collaborate with peers, and contribute meaningfully to the software development community.

“Dig Deeper” serves as a guiding principle for aspiring software craftsmen, urging us to move beyond surface-level understanding and embrace the depths of our craft. By cultivating curiosity, seeking deeper insights, and mastering fundamental concepts, we pave the way for growth, innovation, and excellence in our profession.

From the blog CS@Worcester – Hieu Tran Blog by Trung Hiếu and used with permission of the author. All other rights reserved by the author.

Nurture Your Passion

The Nurture Your Passion pattern is about how important it is to protect and grow your passion for software craftsmanship even in some environments where it might not be supported. This pattern also talks about the challenges that people as software developers face in certain environments where their passion for the craft isn’t supported. Not only does it acknowledge the challenges faced by software developers in environments that may not fully support their passion but also provide strategies to navigate and thrive in those situations. Use certain strategies to protect and nurture your passion by working on what you like and drawing your own career path. The pattern shows that the real challenges that software developers face are when their passion for coding isn’t given its due, so they use a strategy to make their work more passionate. I felt like this pattern emphasizes preserving passion when a challenge comes around and finding a nurturing environment for that passion in software development. It’s great advice to work on tasks that interest you and also make sure to look for supportive people who like your ideas to motivate your success. It’s changed the way I think about my career path and how I should go about challenges in that journey, it’s important to be passionate about work but if it doesn’t give you a purpose or challenge you it’s important to find something that does.

 This pattern wants to encourage people to make sure that their career path has a purpose and that they’re passionate about it. It makes me want to be part of an environment that fits my values even if challenging. It’s not just about writing code; it’s about making sure every step in your career journey feels meaningful. seeking out a workplace that aligns with your values, even if it means tackling some tough challenges along the way. This pattern is a reminder that staying driven and having a clear sense of purpose in your career is everything, even when the going gets tough. This pattern wants to remind people of the importance of maintaining enthusiasm and purpose in one’s career path,  even though it comes with some challenges. It encourages self-care, learning, and engagement that can help in long-term success and satisfaction in software craftsmanship.

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

System Testing

The three levels of the software testing process are unit testing, integration testing, and system testing.
Unit testing tests the isolated functionality of each individual unit. 
Integration testing tests the functionality of combining units to ensure they work together as intended. 
System testing tests the software as a whole. 

In my reading about integration testing, I noticed that at some point during this testing phase the system should be tested as a whole. Is system testing just a redundant and more in depth testing methodology focused on this? Sean Coughlin answers this question in his blog “Understanding System Testing in Software Engineering” (https://blog.seancoughlin.me/understanding-system-testing-in-software-engineering) by providing a clear understanding of what system testing is and what it tests for. 

System testing is a software testing phase that assesses a fully integrated software system’s compliance with requirements, covering both functional and non-functional aspects. These non-functional aspects are what makes system testing so comprehensive compared to integration testing when testing the software as a whole. Examples of non-functional testing include; performance testing, security testing, and usability testing.

Coughlin uses an e-commerce website as an example to illustrate system testing and each of its components. Functional testing ensures each feature of the website works as intended, Performance testing ensures the website still works even during peak user times. Security testing ensures the website is robust against cyber threats and that data is handled correctly. Usability testing ensures the website is user-friendly across multiple platforms.

Testing frameworks exist that allow for automated test such as simulating heavy loads for performance testing. User testing on the other hand is typically done manually as it focuses on a user’s experience. This means having a range of people, from developers to stakeholders, testing end-to-end use of the software. 

Overall system testing is testing an application for real world use. This goes much deeper than just functionality of the software. This is the last phase of testing before the software is released to the final product for acceptance testing. Meaning it is important that developers properly system test to identify and fix issues during this phase.

The scope for system testing is even larger than I could have imagined. Coughlin states, “I like to think of system testing as more of an umbrella term that captures lots of different testing forms.” which perfectly describes how system testing encapsulates testing all aspects of a software.

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

Pairwise Testing

Another important topic that we have discussed in CS-443, or Software Quality Assurance and Testing, is known as Pairwise Testing. Pairwise Testing is yet another form of testing, but this type is a little bit different than the rest. Pairwise Testing, sometimes known as all-pairs testing, tests each pair of input parameters in order to make sure that the functions in the system run correctly no matter what the input is, guaranteeing that it will run for every combination. Pairwise Testing is known as a Permutations and Combinations (P&C) based software testing technique. A blog that I found to be really helpful in explaining Pairwise Testing is known as Pairwise Testing | What It Is, When & How to Perform by Kiruthika D. In the blog, she gives an example that helped me understand more. She states “Let’s say you have an application that allows users to enter two numbers, and the application will output the sum of the two numbers. You can use pairwise testing to test all possible combinations of two numbers, such as (1, 2), (2, 3), (3, 4), (4, 5), etc. By testing all the combinations of two numbers, you can be sure that the application is working correctly and will not fail when given different numbers.” This shows that you don’t actually test every single combination, but you test every single input with another input. This way, it makes sure that all of the inputs work instead of testing a potentially infinite amount of combinations.

The actual purpose/use of Pairwise Testing is exactly what I previously stated. It is used to make sure that all combinations of inputs are possible, but you don’t need to test every single combination. It can be extremely helpful as it reduces the amount of time it takes to test the program as well as the amount of effort. While Pairwise testing is a great testing technique, you obviously can’t use it all the time as it involves pairs. As for when to use it, Kiruthika states “Pairwise testing is helpful when testing complex systems that have multiple input parameters and multiple possible values for each parameter. It can significantly reduce the number of test cases that need to be created while ensuring that all possible discrete combinations of parameters are tested. This can help reduce test case creation time and cost and improve the software’s overall quality. Pairwise testing is not appropriate for all types of software testing. As we discussed, it is most effective for systems with multiple parameters and multiple possible values for each parameter. If a system has only a few parameters and a small number of possible values for each parameter, pairwise testing may be unnecessary. Pairwise testing, also, will not be useful if the values of inputs are inappropriate.” Essentially she is saying that Pairwise testing is used for functions that have multiple parameters with multiple values, and the order of parameters doesn’t matter. On top of that, depending on the type of parameter, the technique might not work either. While I personally don’t see myself using this technique in the future, I think that it has the opportunity to be very useful in certain situations, so I’m glad that I was able to understand it more in case I ever need to use it.

Link: https://testsigma.com/blog/pairwise-testing

From the blog CS@Worcester – One pixel at a time by gizmo10203 and used with permission of the author. All other rights reserved by the author.

CS-448 Week 12 Study the Classics

The pattern “Study the Classics” highlights the importance of remembering and familiarizing yourself with foundational topics and the timeless concepts in software development. This is especially true for individuals with practical or self-taught backgrounds. It suggests that rather than feeling overwhelmed by the vast array of literature available, one should focus on reading books that have stood the test of time and continue to offer very valuable insights into the field.

What I find compelling about this pattern is the emphasis on the enduring relevance of classic texts in a rapidly evolving industry. It underscores the notion that while technologies may change, fundamental principles and concepts often remain consistent. Studying these fundamental texts will allow individuals to gain a deeper understanding of underlying principles that drive software development, which enables them to make more informed decisions and adapt to new technologies more effectively.

This pattern influenced my perspective on professional development and has reinforced the importance of continuous learning and reflection in my intended profession. Rather than focusing solely on the latest trends or technologies, I now see the value in investing time to study classic texts that offer timeless wisdom and insights.

While I agree with the overall premise of the pattern, I also recognize the possible limitations to solely relying on classic texts for learning and development. The field of software development is dynamic and multifaceted, and it’s essential to stay abreast of emerging trends and technologies. Therefore, studying the classics is valuable, but it should be complemented by ongoing learning and experimentation to ensure relevance and adaptability in today’s fast-paced industry.

In summary, “Study the Classics” underscores the importance of studying foundational texts in software development to gain a deeper understanding of timeless principles and concepts. While this pattern has reinforced the value of classic texts in my professional development, I also recognize the need for a balanced approach that incorporates both classic wisdom and ongoing learning to navigate the complexities of modern software development effectively.

6. Construct Your Curriculum | Apprenticeship Patterns (oreilly.com)

From the blog CS@Worcester – Jason Lee Computer Science Blog by jlee3811 and used with permission of the author. All other rights reserved by the author.

Unit Testing

For this week’s blog post, I decided to discuss the article “Unit Testing vs Test-Driven Development” by Albert Stec. I chose this article because it compliments the unit testing topic in the syllabus. This article discusses what unit testing is, why its important and how it fits into test driven development.

The first part of this article spends some time defining what a unit test is. Unit test is usually a method that validates a small portion of the source code. So, the unit test is a programmatically written, automatic test. The unit test takes the initial data, passes it to the code under test, and asserts if the execution result is the same as the expected result.” The article then goes on to discuss what a well designed unit test should have.

The five most important parts of writing a good unit test according to the author are that it is fast, isolated, deterministic, readable and simple. “As we can see it looks simple. Although writing efficient unit tests could be complicated depending on the code we want to test. A well-written unit test should be: 1: Fast. A single project can contain a big number of unit tests, even hundreds, or thousands. Moreover, unit tests can be executed often, e. g., while developing a new feature to avoid regression or in CI/CD pipelines. Therefore, they must run as fast as possible. 2: Isolated. A unit test shouldn’t modify or depend on any external state. 3: Deterministic. A unit test should always return the same result no matter how many times we execute it. Of course, if nothing is changed between runs. 4: Readable. Unit tests are code that needs to be maintained. Therefore, it should be clear and easily understandable. 5: Simple. Often we can read that the unit test should contain a single assertion. Although it can be discussable, the fact is unit tests should validate small portions of the source code.” The next part of the article discusses the importance of unit testing in regard to software development.

This last part of the article discusses how unit testing is important to unit testing development. “To write appropriate unit tests before the logic developers spend more time on analyzing and understanding the problem and its domain. Therefore, the code is more likely to meet all requirements and clients’ needs. It’s one of the most important aims of TDD. The cycles play an important role, as the tests become more specific with time while the implementation becomes more generic.”

Article: https://www.baeldung.com/cs/unit-testing-vs-tdd

From the blog CS@Worcester – P. McManus Worcester State CS Blog by patrickmcmanus1 and used with permission of the author. All other rights reserved by the author.