|
| 1 | +# Unit Testing Guide for EOS Plugin for Unity |
| 2 | + |
| 3 | +## Introduction to Unit Testing |
| 4 | + |
| 5 | +Unit testing is a software testing technique in which individual components of the code are tested to ensure they work as expected. Each unit test should focus on a single function, class, or method and provide immediate feedback on whether that piece of code is functioning correctly. The goal is to catch and address bugs early in development, ensuring a stable and maintainable codebase. |
| 6 | + |
| 7 | +### Benefits of Unit Testing |
| 8 | +- **Improved code quality:** Unit tests ensure that code functions as expected before it is merged into the main codebase. |
| 9 | +- **Early bug detection:** Tests provide an opportunity to catch and fix issues during development. |
| 10 | +- **Facilitates refactoring:** With a solid unit test suite, developers can confidently refactor code knowing tests will highlight regressions. |
| 11 | +- **Code coverage:** Tests help measure how much of the codebase is covered, ensuring critical functionality is always tested. |
| 12 | + |
| 13 | +## Testing Frameworks in Use |
| 14 | + |
| 15 | +Historically, this project has used both **NUnit** and the **Unity Test Framework** for unit testing. However, moving forward, we are transitioning to using **NUnit** exclusively. NUnit offers more flexibility and integration options for broader test case management and is better suited for the long-term needs of this project. |
| 16 | + |
| 17 | +While there are still some existing tests using the Unity Test Framework, all new tests should be written using **NUnit**. This will ensure consistency across the test suite and streamline the development process. |
| 18 | + |
| 19 | +### Why NUnit? |
| 20 | + |
| 21 | +- **Flexibility:** NUnit supports a wide range of assertions, test case parameters, and test fixtures. |
| 22 | +- **CI/CD Compatibility:** NUnit can be easily integrated into Continuous Integration and Deployment pipelines (planned for future). |
| 23 | +- **Broad usage:** NUnit is a widely-adopted framework, making it familiar to many developers and well-supported across different IDEs. |
| 24 | + |
| 25 | +## Scope of Unit Testing |
| 26 | + |
| 27 | +Unit tests should be written for **scripts used in the sample scenes** and for the **core plugin code**. The following guidelines outline the scope: |
| 28 | + |
| 29 | +### What is a priority to test: |
| 30 | +- Core plugin functionality (e.g., helper classes, business logic, utilities, etc.). |
| 31 | +- Scripts attached to game objects or components in the sample scenes (but not the scenes themselves). |
| 32 | + |
| 33 | +### What is _not_ a priority to test: |
| 34 | +- The **EOS SDK**, and it's C# wrapper. The behavior of the SDK and the C# wrapper provided with it is (currently) outside the scope of this project’s unit tests. |
| 35 | +- **Sample scenes** (for now). Tests should focus on scripts, not scene setups or interactions between objects within the scenes. |
| 36 | + |
| 37 | +## Writing Unit Tests |
| 38 | + |
| 39 | +### Basic Structure of a Unit Test |
| 40 | + |
| 41 | +Every unit test should follow these basic steps: |
| 42 | +1. **Setup**: Initialize the objects or dependencies that will be tested. |
| 43 | +2. **Act**: Execute the method or function you are testing. |
| 44 | +3. **Assert**: Verify that the results are what you expect. |
| 45 | + |
| 46 | +```csharp |
| 47 | +[TestFixture] |
| 48 | +public class ExampleTest |
| 49 | +{ |
| 50 | + [Test] |
| 51 | + public void Addition_ShouldReturnCorrectSum() |
| 52 | + { |
| 53 | + // Arrange |
| 54 | + int a = 5; |
| 55 | + int b = 3; |
| 56 | + |
| 57 | + // Act |
| 58 | + int result = a + b; |
| 59 | + |
| 60 | + // Assert |
| 61 | + Assert.AreEqual(8, result); |
| 62 | + } |
| 63 | +} |
| 64 | +``` |
| 65 | + |
| 66 | +### Coverage Requirements |
| 67 | + |
| 68 | +Any **new functionality** added to the project should come with complete unit test coverage. The goal is to ensure that every feature introduced is tested thoroughly. |
| 69 | + |
| 70 | +When **refactoring** existing code, make sure that the unit tests are updated accordingly. Refactors should never lead to a reduction in test coverage. |
| 71 | + |
| 72 | +### Handling Dependencies |
| 73 | + |
| 74 | +While there is no current implementation for **mocking the EOS SDK**, this functionality is in development. Once mocking support is available, you will be able to write unit tests that mock dependencies on the EOS SDK. |
| 75 | + |
| 76 | +For now, focus on isolating business logic and core plugin functionality in your tests. |
| 77 | + |
| 78 | +## Moving Forward: Code Coverage Goals |
| 79 | + |
| 80 | +As we transition fully to NUnit and increase our test coverage, the goal is to reach and maintain high code coverage across the entire project. To facilitate this, developers should: |
| 81 | +- Write tests for all new code. |
| 82 | +- Update tests when refactoring or modifying existing code. |
| 83 | +- Ensure tests are well-structured, easy to read, and maintainable. |
| 84 | + |
| 85 | +## Best Practices for Unit Tests |
| 86 | + |
| 87 | +- **Small, isolated tests**: Each test should focus on a single function or method. |
| 88 | +- **Meaningful names**: Test methods should clearly describe the scenario being tested. |
| 89 | +- **Consistency**: Follow a consistent structure for arranging, acting, and asserting in your tests. |
| 90 | +- **Avoid testing too much at once**: Unit tests should focus on small, testable components, not entire systems. |
| 91 | +- **Repeatable and fast**: Tests should be able to run quickly and consistently without dependencies on external services or the environment. |
| 92 | + |
| 93 | +## Naming Conventions for Unit Tests |
| 94 | + |
| 95 | +To maintain clarity and consistency, unit test names should follow these conventions: |
| 96 | + |
| 97 | +1. **Use Descriptive Names**: Test names should clearly describe the scenario being tested and the expected outcome. Follow the pattern: |
| 98 | + `MethodName_Scenario_ExpectedOutcome` |
| 99 | + |
| 100 | + - Example: `CalculateTotal_WithValidInputs_ReturnsCorrectSum()` |
| 101 | + |
| 102 | +2. **PascalCase**: Use PascalCase for test method names, capitalizing each word. |
| 103 | + - Example: `Login_WithInvalidPassword_ThrowsException()` |
| 104 | + |
| 105 | +3. **Group Tests by Class or Method**: Create test classes named after the class being tested, with `Tests` appended. |
| 106 | + - Example: `OrderProcessorTests` |
| 107 | + |
| 108 | +4. **Arrange-Act-Assert**: Use comments or whitespace to clearly separate the three stages of each test. |
| 109 | + - Example: |
| 110 | + ```csharp |
| 111 | + [Test] |
| 112 | + public void GetPrice_WithDiscountApplied_ReturnsDiscountedPrice() |
| 113 | + { |
| 114 | + // Arrange |
| 115 | + var product = new Product(100); |
| 116 | + product.ApplyDiscount(10); |
| 117 | + |
| 118 | + // Act |
| 119 | + var result = product.GetPrice(); |
| 120 | + |
| 121 | + // Assert |
| 122 | + Assert.AreEqual(90, result); |
| 123 | + } |
| 124 | + |
| 125 | +5. **One Assertion Per Test**: Focus on testing one aspect of the method or functionality in each test. If multiple assertions are needed, ensure they are related to the same scenario. |
| 126 | + - Example: `SaveOrder_WhenOrderIsValid_CreatesNewOrderRecord()` |
| 127 | + |
| 128 | +6. **Edge Cases**: Use specific names when testing edge cases or invalid inputs. |
| 129 | + - Example: `Withdraw_WithInsufficientFunds_ThrowsInsufficientFundsException()` |
| 130 | + |
| 131 | +7. **Avoid Ambiguity**: Test names should avoid ambiguous phrases such as "Can" or "Does". |
| 132 | + - Example: `ProcessPayment_WithValidCreditCard_ReturnsSuccess()` |
| 133 | + |
| 134 | +8. **Setup and Teardown Methods**: Use clearly named `[SetUp]` methods for common setup logic. |
| 135 | + - Example: `InitializeOrderProcessor()` |
| 136 | + |
| 137 | +Following these conventions will ensure that tests are easy to read, maintain, and extend over time. |
| 138 | + |
| 139 | +## Additional Reading and Resources |
| 140 | + |
| 141 | +To further your understanding of unit testing and best practices, the following resources are highly recommended: |
| 142 | +- [NUnit Documentation](https://docs.nunit.org/) |
| 143 | +- [Unity Unit Testing Guide](https://learn.unity.com/tutorial/unit-testing) |
| 144 | +- [Best Practices for Writing Unit Tests](https://martinfowler.com/bliki/TestPyramid.html) |
| 145 | + |
| 146 | +## Conclusion |
| 147 | + |
| 148 | +This guide provides a primer for adding unit tests to this Unity project. Following the outlined principles will ensure high test coverage, improved code quality, and a stable development environment. |
0 commit comments