Category Archives: Week 9

Writing Great Unit Tests

In the blog post Writing Great Unit Tests: Best and Worst Practices, Steve Sanderson talks about the best and worst practices when writing unit tests. He goes over the true purpose of unit tests (each examining a unit of your code separately and as a whole cohesively working together to provide value that is more complex and subtle than the sum of its independently tested parts, not for finding bugs), as well as the purpose of integration tests (automate the entire system to detect regressions). At the end of his post, he also gives several useful tips for writing great unit tests, such as making each test orthogonal, or independent, to all other tests.

The reason I chose to talk about this blog post is because I think it’s definitely something that’s commonly overlooked by developers. As Sanderson said at the beginning of his post, “Even if you’re a brilliant coder with decades of experience, your existing knowledge and habits won’t automatically lead you to write good unit tests.” For people looking to get into software development, I think it’s important to learn how to write great unit tests early on so as to avoid having to clean up a self-inflicted mess in the future.

I found it interesting when he described the difference between unit tests and integration tests, as well as the problems that bad unit tests can cause. This image found in his post is useful for visualizing this:

image

The last section in which he gives practical advise for writing great unit tests is also something that I think will be useful in the future, although I think the formatting may have been messed up.

One thing that I have a hard time not necessarily agreeing with but understanding is how he said that unit testing isn’t for finding bugs. I think that, for example, if you were to make a change to the way a function performs its task (perhaps to optimize the code) while not trying to affect the end result, one of your unit tests failing because of this could be classified as “finding a bug.”

Source: http://blog.stevensanderson.com/2009/08/24/writing-great-unit-tests-best-and-worst-practises/

From the blog CS@Worcester – Andy Pham by apham1 and used with permission of the author. All other rights reserved by the author.

Anti-patterns

This blog https://effectivesoftwaredesign.com/2010/12/22/identifying-anti-patterns/ titled “Identifying Anti-Patterns” discusses what it refers to “anti-patterns”, a category of common code practices that resemble the organizational structure provided by the use of design patterns, but are actually counterproductive and not a good design. I think that the existence of anti-patterns is interesting; in an effort to write code that is well structured and easy to follow, it is actually made worse. The blog post points out that anti-patterns are most commonly used by programmers who are inexperienced and end up writing code with bad design and bad performance, but it is also possible for experienced programmers to do well in implementing a good design, but at the cost of a significant sacrifice on performance. In general I think it would be common for the implementation of a design pattern to have some performance trade-off with readability and maintainability, so there must be some line as to where a design pattern would become an “anti-pattern” if it were to cause some level of a decrease in performance. Design patterns are commonly used for the sake of scalability so that a program with a well-structured foundation will be easier to maintain as it becomes larger, but these design patterns that are implemented during the beginning of the development of the program may seem like unnecessary anti-patterns that are unnecessarily abstract for the current scope of the program. It may be difficult to identify anti-patterns given that excuses and arguments can be made for why code should be implemented in a certain way. Over-complicating things has an impact on performance, but an organized foundation is well suited for a large project, and re-implementing a lot of code as a project grows would likely be more counterproductive than being careful from the beginning. There definitely are some practices that are objectively wrong, but this blog post does not go into any examples, and it is also possible that what may be identified as an anti-pattern could be a false positive. When there is a trade-off between design and performance, it makes the most sense for an anti-pattern to refer to a mistake that is ineffective in both areas.

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

(NaN == NaN) == false

In this blog post https://medium.com/engineering-housing/nan-is-not-equal-to-nan-771321379694 “NaN is not equal to NaN!”, Dron Rathore discusses the IEEE standard of NaN being a value which is not equal to itself. The blog explains some of the definitions and implementations surrounding NaN. It is not an opinionated blog post, it is mainly for the sake of being an educational resource. My particular interest is the actual reason in the first place for why NaN is defined as not being equal to itself. The result of comparison must be a boolean, so the only options for trying to compare NaN to itself are to return true or false, or error and crash. In mathematics, NaN is effectively “undefined” or “indeterminate”, so something like 0/0 is undefined. The truth value of the equation 0/0 = 0/0 is also undefined; the operation of equality is not defined for values that are not defined themselves unless the operation itself is given additional definition to account for that case, which is what must be done for programming languages so that it results in a boolean value. The choice for that value to be false is peculiar and ultimately seems arbitrary, but it is useful for detecting values that are NaN; if (x == x) is false then x is NaN. This blog post does not directly give any feedback on the reason for this implementation of NaN, it merely describes it, but I would like to get some perspective on how the choice is made and how it is more logical to have NaN not equal to itself over an alternative implementation where it is. Comparisons involving NaN may still result in confusing outputs; infinity > NaN is false, for instance, and so is infinity <= NaN, but “not (infinity <= NaN)” is true. For the sake of software testing, NaN adds a lot of strange edge cases where assumptions about equality lead to contradictions. In these cases, or in any case where it is not okay for NaN to exist, it makes the most sense to just have errors instead of trying to deal with this unique behavior.

From the blog cs-wsu – klapointe blog by klapointe2 and used with permission of the author. All other rights reserved by the author.

Quality Assurance as a Career

I decided to take a somewhat different tack for this week’s post for software quality assurance and testing. Instead of focusing on testing itself, and all there is to it, I found a video from a tester in the field, Alan Richardson, on his advice for someone who is interested in getting into the field.
He strongly urged someone getting started not to think of a position in quality assurance as a “stepping stone” to being a software developer. If you do, you will inevitably find yourself in a dead end because you really aren’t interested in the field. “If you want to be a software developer, start as a software developer.” 
He encourages the viewer to read everything they can on the subject. A lot of it is free, so there is no reason to necessarily buy anything. However, he gives some book recommendations. He gives a good insight why books can be so valuable to learning. “An expert in the field took a year to concentrate everything they know into those pages,” (paraphrased).
He doesn’t value certification, but he realizes that many companies do. I didn’t realize there was certification. Even if I don’t end up getting it, it’s useful to know that it exists. He also said that it is easier to go into testing from designing software. 
He also urged testers to find companies that valued the work they did and that provide opportunities for them. He said that oftentimes testers are paid quite a bit less than they’re worth compared to software designers. Not only is picking the right company important, but you should advocate for yourself because the work you do is important.
I thought that he offered some sound advice. I haven’t seen that much other software quality assurance career advice, but this all seems to fit what I’ve heard over the years for computer science or general career advice. I am excited to start working for a company, perhaps one day as a tester.
Strangely, I don’t often think about all the different positions within the computer science field. I tend to lump everyone as a “software developer,” even if I know there’s a lot more to it than that. I am starting to rethink that and consider going to quality assurance. It is something I enjoy, and it is something I can see myself doing.
YouTube Channel: EvilTester – Software Testing
https://youtu.be/iOA3lxZyFwA

From the blog Sam Bryan by and used with permission of the author. All other rights reserved by the author.

Why Testers Need to Know About Code Refactoring

https://www.softwaretestinghelp.com/code-refactoring/

Refactoring is the practice of improving code without changing the existing functionality. It is used to transform inefficient or complicated code into efficient and simpler code. Some reasons why a piece of code may need to be refactored are:

  • Code smells – indications that serious problems may exist in the code. Some common code smells are redundant code, declared variables that aren’t used anywhere, over-complicated design, and the existence of too many complicated loops or conditionals
  • Technical debt – when shortcuts are used that will require more work to fix later
  • Following agile – agile software development promotes incremental development. If code is changed without proper refactoring, it may create code smells or technical debt

Refactoring code seems like something that only developers need to care about. However, it is something that software testers need to know about as well. When code is refactored, the addition of new code or updating of old code may cause existing unit tests to fail. As a tester, refactoring of code means that in-depth testing and regression testing must be performed. In-depth testing includes all existing user flows to ensure that all functionalities are working the same as before. Regression testing is required to ensure that upgrading a module did not break the functionality of another piece of code. Refactoring code may also cause test automation scripts to fail. When refactored code is tested, scenarios such as business cases, user flows, user acceptance tests, and the existing functionality need to be validated.

I thought this blog post was interesting because I have never thought about refactoring from a tester’s perspective. Even when small changes are made, a tester must make sure that the changes don’t break any other parts of the code or alter the user experience. Since refactoring is only concerned with making existing code more efficient or easier to read, tests should not return different results after refactoring. I learned a few useful terms from this post such as technical debt, in-depth testing, and regression testing. Reading this blog has given me a new perspective on code refactoring and has enhanced my understanding of the topic.

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

The State Pattern

The State Behavioral Design Pattern is one of the GoF Design Patterns. In his series on the Gang of Four design patterns, John Thompson wrote an article on the State Pattern, which he defines as “an important pattern that allows an object to change its behavior when it’s[sic] internal state changes.”

He opens the article by providing an example of a Vending Machine program that will need the State Pattern to be applied to it. One thing I like about the way he writes his examples is how he uses variable names to make it very readable. He could have just had the states as the integers themselves, but his simple and clever use of variable names has given me ideas of how to make my programs more readable in the future.

In order to transform his Vending Machine program from a “monolithic class” into a more adaptable program, John shows us how to implement the State Pattern. He separates each of the four states of the vending machine into their own classes. They each implement an interface that defines the behaviors of the vending machine. These state classes each detail how they handle the behavior in that state. Finally, the vending machine itself which handles the inventory of the vending machine and has methods a lot of methods to handle changing the state of the machine.

Due to designing the code with this pattern, you can add a new state by creating a new concrete class and modifying the vending machine class to handle it. However the currently written states are closed to modification as well, following Open Closed principle. When you compare the example before and after the State Pattern was applied, it becomes apparent why it is so beneficial to use this pattern when it’s appropriate: it makes your code more open to modification and more easily-understood. You don’t have to spend as much time reading and understanding code under the State Design Pattern, and so it helps make your program easy to maintain, especially when multiple people might be going back to the code later. Having more classes isn’t necessarily a bad thing.

From the blog CS@Worcester – Let&#039;s Get TechNICKal by technickal4 and used with permission of the author. All other rights reserved by the author.

Decision Graphs

The article I chose to cover for CS-443 this week is a research article titled Decision Graphs and Their Application to Software Testing by Robert Gold. This article goes in-depth on one of the subjects covered in our Activities, DD-path testing, as well as other decision-based testing methods. One of the things I like about this article is that it uses a lot of mathematical notation and logic to represent how the methods work. It also has very detailed proofs to show why the necessary branch/edge coverage is reached. There are several different examples of code that have corresponding decision graphs, to show the different parts of making a decision graph.

Looking at the example of the function f1 given in the article (Figure 3), there is something this article did with DD-path graphs that we did differently in class. whereas our DD-paths were just all the nodes in between with an in-degree and out-degree of 1, when Robert combines several D-nodes into one DD-path, he includes the first node that has an in-degree of 2 and the last node which has an out-degree of 0 along with the rest of the nodes. Therefore, his DD-Path graph for f1 is a lot simpler than what we would have made doing what we did in class. I’m curious which way is better. The article also dives into a topic about path testing we discussed but did not have an example of, that is when code branches into multiple different endpoints. In order to achieve branch coverage in these examples, you have to have multiple tests with different inputs that satisfy every branch.

Overall, the abundance of examples in both code and their associated graphs, as well as the very clear mathematical notation and rigorous proofs makes this article a really interesting read if you are a Mathematics major/minor. The conclusion at the end details a major application of this are modeling programs with flow graphs to represent programs. There are many different kinds of decision based testing methods that you can use, and if you have any questions about one of them or how they work, this is an amazing resource.

From the blog CS@Worcester – Let&#039;s Get TechNICKal by technickal4 and used with permission of the author. All other rights reserved by the author.

Static vs. Dynamic Testing

Greetings reader!

Today’s blog,  will discuss the differences between static and dynamic testing. I will be briefly explaining the benefits for each test, as well as pointing out their distinct features. I will also be sharing my analysis of Software Testing Help’s-” Static Testing and Dynamic Testing – Difference Between These Two Important Testing Techniques” article from which I read. Without any further babbling, let’s start.

Static testing is a testing technique that takes the form of design reviews, functional requirement reviews, code walkthroughs, business requirement reviews, and test documentation reviews. It is a ongoing activity that is not just done by testers.

In static testing, code is not executed; instead it checks the code, requirement documents, and design documents to detect errors.  The goal of this technique is to improve the quality of software by finding errors in early stages of development. Static testing is often called as non-execution technique or verification testing.

Static Testing Techniques:

  • Informal Reviews
  • Technical Reviews
  • Walkthrough
  • Inspection
  • Static code Review

Dynamic testing is more hands-on and develops on the product itself and not on an a representation of the product. A much formal process of test cases, considerations, and execution explain the dynamic testing methods. Dynamic testing is when you are providing an input, receiving an output, and comparing the output to the expected behavior. It is a system made with the intent of finding errors.

In dynamic testing, code is executed. It checks for working behavior of the software system, memory, and the performance of the system. The goal of this technique is to ensure that the  product works in agreement with  the business requirements. Dynamic testing is used at all levels of testing and it can be either black or white box testing. Dynamic testing is also known as validation testing.

Dynamic Testing Techniques:

  • Unit Testing
  • Integration Testing
  • System Testing

In conclusion, both static and dynamic testing reveal mistakes and coding errors using different methods. Verification (Static) and Validation (Dynamic) are two measures used to check that the software product meets the requirements specifications. Together they try to help improve software quality.

Software Testing Help’s-” Static Testing and Dynamic Testing – Difference Between These Two Important Testing Techniques” helped me a lot when reading about Static vs Dynamic testing.

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

PATTERN : Sustainable Motivations

Sustainable Motivations

The author opens this apprenticeship pattern by addressing all the intangibles that are often overlooked in the programming world. He talks about the challenges we, as developers encounter in our career. He addresses the issues of horrendous real-world projects that are often rigorous,  tedious and exhausting. It can grow from  frustrating at times to morphing into overly chaotic or constraining issues that are backed by a business man who only knows what the current trend demands. All through this, the author urges us to hold firm and ensure that our drive for mastery propels us to withstand the situation.

Personal Reflection

I was fortunate enough to be taking the CS-348 class so i got to witness the dynamics of a software development environment through one of our in class simulations and there i realized that the constant specification changes by the business man often can lead to stressful and frustration environment to work in but it is here that the author tell us ground our motivations to the walking the long road pattern. In that pattern, we are though to continue taking on task that build and molds our skills. So in the mist of all the chaos, we are expected to find a related source of interest in programming that will continue to carry us when the going gets real tough.

I personally feel like this is the hardest pattern to master because normally, programming is challenging so the only thing that keeps us going at it is our passion for coding/ developing software. Now should that passion be attacked, we have no more source of interest. But the author tells us to persist even when we have lost drive and find a secondary source that can fuel us through the tough time until our original passion returns. I do agree that it does get to a stage that being able to provide for you family comes into the equation so this rules out switching of area or quitting in generally and money often serves as the secondary drive that can propel us until we get our initial vision back. The life of a programmer is filled with many adventures, learning slopes and curveballs but finding joy in programming amidst the bad times deepens the love and passion to be great !.

From the blog CS@Worcester – Le Blog Spot by Abranti3 Dada Kay and used with permission of the author. All other rights reserved by the author.

Pattern : Sweep the Floor

Sweep The Floor 

When reading this pattern, i was a little puzzled the first time but after a second read through i understood what the author was insinuating. No one hands over the most important tasks on a project to a graduate they just hired. That would be putting the future of the company in jeopardy. This is mainly because you do not know how competent a person is without seeing their actual work.

Summary

In this chapter, the author brings to light how apprentices can gain trust of their respective teams and build their way to becoming master craftsmen on the team. By “Sweeping The Floor” newcomers or  new hires are able to build a portfolio performing tasks that the other team members would  not like to do. And when performing these tasks, they are to do it with a sense of urgency and purpose. By ways of such means, you are able to build trust, contribute to the team and also demonstrate your level of competency and understanding of the  team tasks.  We often forget that before we get to celebrate the big victory, having multiple little victories builds ones self confidence and skills that would eventually contribute to the “big wins”. 

The author did mention the value of our college degree once we graduate and i think this is the most surreal thing i read from the entire chapter. Knowing that all the time and effort invested in acquiring my degree only goes to raise expectations on what i could potentially bring to the team but doesn’t solidify me as knowing how to develop a software. with this said, the only way to solidify and earn my teams respect as a  programmer is to create well organized code and programs when i work on the less impacting task i am assigned or i volunteer for. Of course “sweeping the floor” is hard when i have completed my degree in hopes of becoming a full time software developer but the key is that, i would still have an opportunity and by doing a tremendous job on assigned tasks, i will be able to make a case for my skills and earn the respect of my  team members. 

From the blog CS@Worcester – Le Blog Spot by Abranti3 Dada Kay and used with permission of the author. All other rights reserved by the author.