Category Archives: CS-443

Testing in Python and Sea

Something that is worth noting is Python’s assert keyword. Python has a built in way to create basic unit tests beyond simply printing and making comparisons. This has me thinking about my Sea programming language.

I think much of the hassle I’ve had with unit testing has come from simply getting the environment set up in the first place. If unit tests could be more like a data structure or design pattern – something you know the design of and you can simply implement – I think that would simplify a lot. So while I could create a Sea library for unit testing similar to numerous other libraries (or wait for someone else to make one in Sea), I’d prefer to create a more internal solution.

Sea is fundamentally C, so that means it doesn’t have a lot of high level features that can make unit testing easier. I mean, Sea isn’t even object oriented. That said, the entire design philosophy behind Sea is based on simple syntax that doesn’t add a runtime performance cost. One way I could achieve this is by adding another “stage” to the language. The current design of Sea involves a preprocessor, a lexer, a parser, and a visitor (interpreter, transpiler, or compiler). What I could do is add a tester that would run before the visitor, to test compile-time things (checking types or any other value known at compile time) and then a runtime tester. These could be modular features of the language itself and could be removed if desired.

Another simple solution is to add a handful of keywords to Sea similar to assert. The problem with that is C doesn’t have runtime exceptions. The design would have to be based on the notion that the program is the unit tests. I’ll continue to think this over. After all, Sea is still in its early stages. I’m currently rewriting it (just on the visiting functions now) and then I’ll add functions, pointers, etc. However, if Sea is to become a real, usable language then there will have to be ways of testing code; the simpler and more convenient, the better. After all, that’s the whole point of Sea.

From the blog CS@Worcester – The Introspective Thinker by David MacDonald and used with permission of the author. All other rights reserved by the author.

Converting a Project to Gradle

A few weeks ago, a few classmates of mine asked for some help with converting code to Gradle and I created a quick guide. I’d like to go through and create another guide with more detail.

Assumptions

  • You have Gradle installed.
  • You know which language you are using.

Instructions

The first step is to run gradle init in the project folder that you wish to convert to gradle. I would recommend if you’re unsure about the process or the settings you’ll use, just create an empty folder somewhere and practice creating a gradle project in that. Then, delete it.

Note that depending on the options you choose, you may be asked questions I do not cover here. Just do your best to figure out what it means and use the internet for research. Worst case, you can always modify the settings afterwards.

When you run gradle init, you will be asked some questions about your project. You simply type the number corresponding to the option you want and then press enter (or simply press enter without a number for the default option). In our classes, we always used libraries. If you have a main method, you’ll probably want application.

Next, it will ask you for the language you want to use. This is probably the simplest question. In our classes, we’ve used Java but you can use any of the displayed programming languages.

Next, is the build script DSL. If you don’t have a strong opinion on this, just use the default.

Similarly, next is the testing framework. Use whatever you’re comfortable with. In our classes, we’ve used JUnit Jupiter.

Next you can name the project anything you like.

This last step where it asks for source package for Java is a step where many people mess up. The default option is an undesired package name, since it will include capital letters. I recommend using a lowercase package name.

Now, you can open lib/build.gradle. You can remove the lines and comments for api and implementation. These are auto-generated, but not necessary. Next, if you plan on using GitLab’s ci, modify the testRuntimeOnly line. Notice how the testImplementation line has a version number following a colon. Modify the testRuntimeOnly line so it has the same version as the testImplementation. After these steps, my dependencies looked like this:

dependencies {
// Use JUnit Jupiter API for testing.
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.2'

// Use JUnit Jupiter Engine for testing.
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.2'

}

Now, gradle will have created a gradle/lib, gradle/app, etc folder. Locate your package which will be a subdirectory of gradle/lib/src/main/java in my case. The main folder will contain your source files and the test folder will contain your tests. Move all of your source files into main/PACKAGE_NAME and move all of your tests into test/PACKAGE_NAME. You can delete the files gradle generated for you.Then, if you’re using java, you’ll need to go into each java file and add a package declaration. Make sure its the first line and that there is only one. It should look like:

package PACKAGE_NAME;

Where PACKAGE_NAME is replaced with the package name. You can then run tests with the gradle test command. If you want to have GitLab run your tests for you when you push a new commit, download .gitlab-ci.yml (ideally the newest version so not from this link) and add it to your repository. Now, things should hopefully work.

Closing Comments

It’s taken us a while to become familiar with Gradle so I think it was worth me writing all of this down (albeit hastily) to help other people in the future, and especially to help me remember it if I ever use Gradle again in the future.

From the blog CS@Worcester – The Introspective Thinker by David MacDonald and used with permission of the author. All other rights reserved by the author.

Automated Testing

Automated testing is a great option for repetitive tests such as regression and functional testing but not useable for testing methods such as discovery and usability testing that requires a human to do the work. If used correctly, automated testing can save a lot of time and therefore money. If used incorrectly, it could end up costing more than manual testing.

Certain requirements that the testing process to be automated must meet are that it is repeatable, determinant, and non-opinionated. The first requirement, repeatable, means that it must be ran more than once, or else there would be no reason to automate it. Repeatable tests have three steps: set up the tests with data and environment, execute the function and measure the result, and clean up the data and environment after testing. The second requirement, determinant, means that the outcome will be the same every time the function runs with the same input. For example, when inputted 1 and 2 to an addition function, the outcome 3 must be produced every time it is ran with those inputs. The third requirement, non-opinionated means that there must be a concrete answer. You cannot automate opinionated feedback.

Now that we talked about the requirements of automated testing, now we will discuss the three steps of automated testing: prepare, take action, and report results. In the first step, prepare, you set up the data and test environment where the tests occur. This will require either manipulation of the data or putting the program in a certain state, or both. The second step, take action, the driver will run the tests. This will happen by calling the code directly, or accessing a programs api or user interface. And lastly, report results. The automated system will record and report the results from the test.

When used properly, test automation can save money and time and provide quality test results.

Source:

Testim. (2020, February 03). What is test automation? A simple, clear introduction. Retrieved May 03, 2021, from https://www.testim.io/blog/what-is-test-automation/

From the blog CS@Worcester – Austins CS Site by Austin Engel and used with permission of the author. All other rights reserved by the author.

JaCoCo

After taking a quick look at JaCoCo in class I wanted to learn a bit more about it. This article is an introduction to using JaCoCo and gives some good examples.

The article explains that when you write tests there are some criteria to consider:

  • We want to make sure that the parts of the code that are best tested are the parts that are most likely to contain bugs.
  • We want to focus our tests on parts of the application that are critical, the parts where bugs are most likely to lead to a bad outcome for our customers.
  • We don’t want to write tests that repeatedly cover the same areas of the code while ignoring other parts of the code.

You can find which parts of the code are the most likely to have bugs by finding the most complex parts. A common way to do this is using cyclomatic complexity (check the article for the algorithm).

JaCoCo measures code coverage, can report on the complexity of each method, and can tell you how much complexity is untested. In the article a lot of the things we covered in class are repeated, but it helps to see it again to reinforce the concepts and also to reference for the future. While we spoke about it in class, a lot of the things that are said are not recorded anywhere.

The article also brings up the use of JaCoCo to measure complexity. After getting as much code coverage as possible you can refactor your code if the complexity score is too high. In the example they reduce a method’s complexity from 21 points to 9 points. That just goes to show how useful JaCoCo is. After reducing complexity and improving code coverage you can be confident your code is ready for a code review.  

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

Static vs. Dynamic Testing

Software testing falls largely into two categories: static and dynamic. Both are valuable, but the scenario around the test being performed determines which method best fits.

Static testing is a testing technique that does not require the code to execute. This can include manual or automated reviews of the code, requirement documents, and document design, all of which are intended to catch errors in the code. Static testing is done in order to prevent errors during the early stages of development and can help locate errors undetected through dynamic testing methods. Reviews are an important facet of static testing and are the primary method for carrying out a static test. A review is a meeting or other process aimed at locating flaws and defects in the design of a program. Apart from physical walkthroughs of the code, there exist tools that automatically search for errors. These tools, such as CheckStyle and SourceMeter, can help developers adhere to standards in code and style.

Dynamic testing is a testing technique that checks the program’s behavior when code is executed. As the name suggests, it is intended to test the dynamic behavior of a software. This encompasses a vast majority of the testing methods we’ve discussed both in this class and on this blog. The two types of dynamic testing are white and black box testing, which are both techniques that I have discussed on this blog before. Dynamic testing ensures that a software is working properly during and after its installation, it makes sure that the software is stable, and it encourages consistency in the software’s functionality.

Sources:
https://www.guru99.com/testing-review.html
https://www.guru99.com/dynamic-testing.html

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

Decision Table – Based Testing

For the fourth assignment in software testing, we had to create a decision table testing. A decision table is a black-box test technique that visually presents combinations of inputs and outputs, where inputs are conditions or cases, and outputs are actions or effects. A full decision table contains all combinations of conditions and actions. Additionally, it shows the causes and effects. Therefore, this technique is also called a cause-effect table. A well-created decision table can help to sort out the right response of the system, depending on the input data, as it should include all conditions. It simplifies designing the logic and thus improves the development and testing of our product. 

The decision table works on input conditions and actions. We create a Table in which the top rows are input conditions, and in the same vein, the bottom rows are resulting actions. Similarly, the columns correspond to unique combinations of these conditions.

Advantages of Decision Table Testing

The system behavior is different for different input, both equivalent partitioning, and boundary value analysis won’t help, but decision table can be used.

It can be easily interpreted and is used for development and business as well.

Help to make effective combinations and better coverage for testing.

Any complex business conditions can be easily turned into decision tables.

In a case we are going for 100% coverage typically when the input combinations are low, this technique can ensure the coverage.

Disadvantages of Decision Table Testing

The number of inputs increases the table will become more complex.

Resources:

https://www.guru99.com/decision-table-testing.html

From the blog CS@Worcester – Tech, Guaranteed by mshkurti and used with permission of the author. All other rights reserved by the author.

Static Testing Tools

As this is the last blog I will be writing for this course, I thought it would appropriate to have it be about one of the final topics that I’ve learned; static testing tools. First of all, what is static testing? It’s a form of software testing that tests the code without needing to execute it. This method of testing is useful for finding and resolving errors during the early stages of the program. This also reduces the amount of potential errors that could appear during later stages of development. There are tools which are used to accomplish this form of unit testing that I’ve had some recent experience with. I’ve learned about a few of these static testing tools, and the ones that I would like to touch upon in this blog are checkstyle and Jacoco.

Checkstyle is one of the first static testing tool that I’ve used, and so I’ll talk about it first. The purpose of this tool is to check that the code being tested follows a specific coding guideline that has been preset. The process of doing so it automatic and so it allows the tester to be able to make sure that the coding standard is properly followed while also being able to save time of checking this themselves. While this tool can improve the quality in the presentation of the code, it can’t detect any coding errors having to do with the logic of the code.

Jacoco is a static testing tool that provides code coverage. It measures line and branch coverage by running various test cases, and displays the result with a visual report that shows which lines of code have been tested and the percentage of the amount of code that executes in each method. This allows the tester to be able to determine which parts of the code need more development.

Static testing tools are great resources for unit testing and can improve the overall development of the program by checking for errors at an early stage. These tools can be used simultaneously to check for multiple issues with a program at once. Checkstyle and Jacoco can both provide information to the tester that allows them to be aware of errors at each stage of the code, which makes the process of development more clear when building the program.

Useful links:
https://www.guru99.com/testing-review.html
https://checkstyle.sourceforge.io/
https://www.blueacornici.com/blog/code-coverage-with-jacoco/

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

Test Doubles

Test doubles are a method of unit testing that allows a user to test how the code interacts with an external dependency. It is intended to focus on the code being tested rather than the behavior of the external dependencies. As such, a preset object is used to represent those dependencies and their intended behavior. This allows a section of code to be tested even when its external dependencies are not yet finished or are not yet working. There are several types of objects used as test doubles: dummies, fakes, stubs, and mocks.

Dummies are objects that are passed but never used. In most instances, they are only used to fill out a parameter and are used as a placeholder for arguments.

Fakes are objects that simulate the external dependency by implementing the same interface without interacting with any other objects. Fakes are typically hard-coded in order to represent the correct behavior and must be modified whenever the interface is modified. A new fake object must be created for every unique test case.

Stubs are objects which return a result based on specific input, and they do not usually react beyond the scope of the test. Stubs will usually have all the methods required by the external dependency but will provide hard-coded returns that may need to be altered depending on the test case.

Mocks, much like stubs, will return a result based on a specific input. Mocks can also be programmed with data like the number of times its methods should be called and in what order.

Sources:
https://devopedia.org/mock-testing
https://www.telerik.com/products/mocking/unit-testing.aspx

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

Code Reviews

This week I wanted to learn a little more about code reviews. As first I thought, “Yeah code reviews just get someone to look at your code isn’t that common sense?”. After looking into it more I learned code reviews have a lot of benefits that you might not think of.

Code reviews share knowledge. Most people are going to be working as part of a team. With code reviews there is always more than one person that understands some portion of the project. This makes the team more flexible. With this shared knowledge also comes a better ability to estimate how much work some portion of the project is. When the reviewer gives feedback the are also exposed to the complexity that may underlie an issue. This gives multiple informed inputs to create more reliable estimates for the team.

Code reviews also give you a break from the monotony of a certain task. If you are spending a lot of time on a certain part of the project, doing a code review is like a breath of fresh air. It is liberating to work on a different area of the project. It can even feel fun, almost like a vacation.

Code reviews can also motivate developers to work harder. When you know one of your peers is going to take a look at your work you might take an extra effort to create something you find presentable. You would want your code to be clean and for all your tests to pass.

Code reviews are really more than just having someone else look at what you have done. They are an important part of any software development team and deserve to be formally incorporated into the development process.

atlassian.com/agile/software-development/code-reviews

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

Erockwood Post #5

An important part of software testing is the testing of the software itself. But what if you were able to automate the testing? One of every programmers core ideals is to try to automate as much as possible, because programmers are “lazy”. One framework that allows you to do this is Gradle. Gradle is a build automation tool rooted on JVM, so it is perfect to use with Java. We can use GitLab’s Continuous Integration tool to allow our code to run and test every time it is pushed to GitLab. This is very useful so that any changes made are automatically test each and every time an update is pushed to Main. Once you have your Java project set up, you need to initialize Gradle into the directory of the Java project. After you have done that, you can copy your Java files to the Main src folder in the new Gradle section in the directory. All of your test files will go to the Test src folder. You can then run gradle build to build the project, then gradle test to run all of your tests in the test files using the files in the Main folder.

After this and gradle test outputs successfully, you can set up GitLab’s Integration by using the .gitlab-ci.yml file in your project. After you have added that, all you need to do is use Git to commit and push your project to GitLab and then check the CI/CD tab to watch your tests run.

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