C# WinForms inventory management application modernized with DevOps practices, including unit testing and CI/CD.
- Language: C# (.NET 10.0)
- UI Framework: WinForms
- Testing: xUnit
- CI/CD: GitHub Actions
- Containerization: Docker
| Version | Framework | Notes |
|---|---|---|
| 1.0 | .NET 5.0-windows | Original submission |
| 2.0 | .NET 10.0-windows | Upgraded for long-term support, DevOps modernization |
This project was originally built targeting net5.0-windows, which reached end of life in May 2022.
As part of modernizing this project for the use of practicing and testing DevOps principles, the target framework was
upgraded to net10.0-windows — the current LTS release — to ensure compatibility with modern
tooling, GitHub Actions runners, and current xUnit test frameworks.
Changes made during upgrade:
-
Updated
<TargetFramework>in.csprojfromnet5.0-windowstonet10.0-windows -
Resolved NuGet package compatibility issues introduced by the framework change
-
Added a separate xUnit test project targeting
net10.0-windowsto match the main project -
The WinForms UI layer is not containerized (Windows-only dependency)
-
InventorySystem.Logiccontains the cross-platform business logic -
All 21 tests pass inside the container on Linux
InventorySystem/
├── InventorySystem-EmilyCarter.sln # Solution file
│
├── InventorySystem-EmilyCarter/ # Main project
│ ├── dataParts/
│ │ └── SelectionMode.cs
│ ├── helper/
│ │ └── validator.cs # Validation logic
│ ├── model/
│ │ ├── Inhouse.cs
│ │ ├── Inventory.cs
│ │ ├── Outsourced.cs
│ │ ├── Part.cs
│ │ └── Product.cs
│ ├── AddPart.cs
│ ├── addProducts.cs
│ ├── InventoryMain.cs
│ ├── modifyParts.cs
│ ├── ModifyProduct.cs
│ ├── Program.cs
│ └── InventorySystem_EmilyCarter.csproj
│
└── InventorySystem.Tests/ # xUnit test project
├── ValidatorTests.cs # Unit tests for validator logic
└── InventorySystem.Tests.csproj
This project includes a Docker container for running the logic layer and tests in a cross-platform environment.
docker build -t inventorysystem:2.0 .docker run --rm inventorysystem:2.0 dotnet test InventorySystem.Logic.Tests/InventorySystem.Logic.Tests.csproj --verbosity normaldotnet run --project InventorySystem-EmilyCarter/InventorySystem_EmilyCarter.csprojdotnet test InventorySystem.Tests/InventorySystem.Tests.csproj| Test | Description | Status |
|---|---|---|
ValidateMinMaxValues_ValidInputs_ReturnsTrue |
Valid min/max returns true | ✅ Passing |
ValidateMinMaxValues_MinEqualsMax_ReturnsTrue |
Min equal to Max is allowed | ✅ Passing |
ValidateMinMaxValues_MinGreaterThanMax_ReturnsFalse |
Min greater than Max fails | ✅ Passing |
ValidateMinMaxValues_NegativeMax_ReturnsFalse |
Negative Max fails | ✅ Passing |
ValidateMinMaxValues_NegativeMin_ReturnsFalse |
Negative Min fails | ✅ Passing |
ValidateMachineID_ValidInput_ReturnsTrue |
Contains Valid String | ✅ Passing |
ValidateMachineID_EmptyInput_ReturnsFalse |
Is not null | ✅ Passing |
ValidateMachineID_NegativeInput_ReturnsFalse |
Does not contain negative int | ✅ Passing |
ValidateMachineID_WhitespaceInput_ReturnsFalse |
Does not contain whitespace | ✅ Passing |
ValidateCompanyName_ValidInput_ReturnsTrue |
Company Name Matches Input/Output | ✅ Passing |
ValidateCompanyName_NullInput_ReturnsFalse |
Is not null | ✅ Passing |
ValidateCompanyName_ContainsNumbers_ReturnsFalse |
Does not contain integers | ✅ Passing |
ValidateCompanyName_ExceedsMaxLength_ReturnsFalse |
Input does not exceed max length | ✅ Passing |
ValidateCompanyName_BelowMinLength_ReturnsFalse |
Input below Min Length | ✅ Passing |
ValidateCompanyName_ValidInputWithWhitespace_ReturnsTrueAndTrims |
Happy Path and returns trims | ✅ Passing |
- Separation of concerns — extracting pure logic from WinForms-coupled classes to make them unit testable
- xUnit testing fundamentals — Arrange/Act/Assert pattern
- Professional solution structure with a separate test project
- Framework migration from .NET 5.0 to .NET 10.0
- Git workflow — feature branches, pull requests, and clean commit history
[Theory]vs[Fact]— when to test multiple inputs with a single test method- Docker containerization — why WinForms cannot be containerized and how to isolate the logic layer
- Cross-platform development — the difference between
net10.0-windowsandnet10.0 - Class libraries — separating reusable logic into a
.dllfor use across projects .dockerignore— keeping containers lean by excluding build artifacts- Static state in tests — why shared collections cause test pollution and how constructors solve it
- Real bug fixing — improving
DeletePartto return accurate success/failure results