Skip to content

feat: add unit testing framework and tests for SSH and Container Registry#281

Open
publi0 wants to merge 5 commits intoMagaluCloud:mainfrom
publi0:feat/unit-tests
Open

feat: add unit testing framework and tests for SSH and Container Registry#281
publi0 wants to merge 5 commits intoMagaluCloud:mainfrom
publi0:feat/unit-tests

Conversation

@publi0
Copy link
Copy Markdown
Contributor

@publi0 publi0 commented Mar 15, 2026

Summary

This PR introduces a unit testing framework for the Terraform Provider MGC, along with comprehensive test coverage for two products as reference implementations:

  • SSH Keys (datasource + resource)
  • Container Registry (6 datasources + 2 resources)

Motivation

The project currently lacks unit tests for its Resources and Data Sources. While acceptance tests (acctest) validate the full Terraform lifecycle against real infrastructure, they are slow and require cloud credentials. Unit tests fill a critical gap by enabling fast, isolated validation of provider logic — data mapping, error handling, change detection, and state management — in milliseconds, without cloud dependencies.

How the unit tests work

The approach is based on dependency injection with mocked SDK services:

  1. Mock generation: SDK service interfaces (e.g., RegistriesService, KeyService) are mocked using mockery, generating implementations in mgc/internal/mocks/
  2. Direct method invocation: Instead of going through Terraform's full lifecycle, tests instantiate the Resource/DataSource directly, inject the mock, and call Create, Read, Update, Delete methods
  3. Schema helpers: A shared testutils package (mgc/internal/testutils/tf_helpers.go) provides GetResourceTestSchema() and GetDataSourceTestSchema() to avoid schema duplication in tests
  4. State/Plan manipulation: Tests build tfsdk.State, tfsdk.Plan, and tfsdk.Config structures to simulate Terraform's internal data flow, then assert on the resulting state

A detailed guide is included in UNIT_TESTING.md at the project root, documenting the patterns, anatomy of a test, and how to extend coverage to other products.

Products covered (as examples)

SSH Keys (mgc/ssh/)

  • ssh_test.goGetDataSources() and GetResources() factory registration
  • datasource_keys_test.go — Read (happy path, empty list, API error)
  • resource_keys_test.go — Full CRUD: Create, Read, Update, Delete, ImportState + error scenarios

Container Registry (mgc/containerregistry/)

  • containerregistry_test.go — Factory registration for 6 datasources and 2 resources
  • datasource_credentials_test.go — Read + Configure (nil/invalid ProviderData)
  • datasource_images_test.go — Read with nested tags, empty list, API error
  • datasource_proxycache_test.go — Single proxy cache Read + error
  • datasource_proxycaches_test.go — List Read, empty list, API error
  • datasource_registries_test.go — Read with nullable proxy_cache_id, empty list, API error
  • datasource_repositories_test.go — Read, empty list, API error
  • resource_proxycache_test.go — Full CRUD + partial update tests (one field at a time) to validate change detection logic + Configure error handling
  • resource_registries_test.go — Create (with/without proxy_cache_id), Read, Update (intentionally unsupported), Delete, ImportState

Code Coverage

Package Before (no tests) After
mgc/containerregistry 0% 77.2%
mgc/ssh 0% 74.1%

Bugs found during testing

Writing these tests exposed real bugs in the source code:

  1. storage_usage_bytes never mapped in datasource_registries.go — The schema defined this attribute, but the Read() method never populated it from the SDK response (registry.Storage). Users would always see a null value. Fixed in this PR.

Files added

Path Description
UNIT_TESTING.md Comprehensive guide on writing unit tests
mgc/internal/testutils/tf_helpers.go Schema helper utilities
mgc/internal/mocks/*.go Auto-generated mock services (mockery)
mgc/ssh/*_test.go SSH Keys unit tests
mgc/containerregistry/*_test.go Container Registry unit tests

Files modified

Path Change
mgc/containerregistry/datasource_registries.go Added missing StorageUsageBytes mapping in Read()

Test plan

  • All 58 container registry tests pass (go test ./mgc/containerregistry/...)
  • All SSH tests pass (go test ./mgc/ssh/...)
  • No existing tests broken
  • Review UNIT_TESTING.md guide for clarity and completeness
  • Validate mock generation instructions work on a clean environment

publi0 added 2 commits March 14, 2026 22:41
Add extensive unit tests for containerregistry datasources and
resources, plus generated mock services. Set StorageUsageBytes in
DataSourceCRRegistries Read to map registry.Storage
Copilot AI review requested due to automatic review settings March 15, 2026 02:03
@publi0
Copy link
Copy Markdown
Contributor Author

publi0 commented Mar 15, 2026

Just to clarify: I intentionally limited the scope of this PR to only two products (SSH Keys and Container Registry) so they serve as reference implementations — showing the patterns, structure, and the kind of bugs these tests can catch.

The goal is not to cover the entire provider in this single PR, but to establish the foundation (framework, helpers, mocks, documentation) so unit tests can be incrementally added to the remaining products.

If you're interested, we could open individual issues for each product (e.g., Block Storage, Kubernetes, Load Balancer, etc.) and I can help contributors add test coverage following the same patterns documented in UNIT_TESTING.md.

@publi0
Copy link
Copy Markdown
Contributor Author

publi0 commented Mar 15, 2026

🥸

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a standardized unit-testing approach for this Terraform provider by adding a testing guide, shared test utilities, mock SDK services, and unit tests across the ssh and containerregistry packages. It also extends the container registry registries data source mapping to include storage usage.

Changes:

  • Add UNIT_TESTING.md documenting a mock-based unit testing pattern for resources and data sources.
  • Add mgc/internal/testutils helpers plus mockery-generated SDK mocks to simplify unit test setup.
  • Add unit tests for SSH and Container Registry resources/data sources, and extend registries data source to map storage_usage_bytes.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
UNIT_TESTING.md New guide describing unit test structure, schema helpers, and mock generation.
mgc/internal/testutils/tf_helpers.go Adds reusable helpers to extract real schemas for unit tests.
mgc/internal/mocks/CredentialsService.go Mockery-generated SDK mock to support unit tests.
mgc/internal/mocks/ImagesService.go Mockery-generated SDK mock to support unit tests.
mgc/internal/mocks/KeyService.go Mockery-generated SDK mock to support unit tests.
mgc/internal/mocks/ProxyCachesService.go Mockery-generated SDK mock to support unit tests.
mgc/internal/mocks/RegistriesService.go Mockery-generated SDK mock to support unit tests.
mgc/internal/mocks/RepositoriesService.go Mockery-generated SDK mock to support unit tests.
mgc/ssh/datasource_keys_test.go Unit tests for SSH keys data source.
mgc/ssh/resource_keys_test.go Unit tests for SSH keys resource CRUD/error paths.
mgc/ssh/ssh_test.go Unit tests for GetResources/GetDataSources factories in ssh.
mgc/containerregistry/datasource_credentials_test.go Unit tests for container registry credentials data source.
mgc/containerregistry/datasource_images_test.go Unit tests for container registry images data source.
mgc/containerregistry/datasource_proxycache_test.go Unit tests for proxy cache data source.
mgc/containerregistry/datasource_proxycaches_test.go Unit tests for proxy cache list data source.
mgc/containerregistry/datasource_registries.go Adds mapping for storage_usage_bytes in registries list.
mgc/containerregistry/datasource_registries_test.go Unit tests for registries list data source incl. storage usage.
mgc/containerregistry/datasource_repositories_test.go Unit tests for repositories list data source.
mgc/containerregistry/resource_proxycache_test.go Unit tests for proxy cache resource CRUD/error paths.
mgc/containerregistry/resource_registries_test.go Unit tests for registries resource CRUD/error paths.
mgc/containerregistry/containerregistry_test.go Unit tests for GetResources/GetDataSources factories in containerregistry.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

AttributeTypes: map[string]tftypes.Type{
"digest": tftypes.String,
"size_bytes": tftypes.Number,
"pullet_at": tftypes.String,
Copy link
Copy Markdown
Contributor Author

@publi0 publi0 Mar 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is indeed a typo — pullet_at should be pulled_at. This is actually one more bug found thanks to the unit tests. Since this change would alter the user-facing schema contract (a breaking change for existing users), it deserves its own dedicated PR to handle the migration properly.

Schema failures should stop the test immediately instead of cascading
confusing errors from running with an invalid/zero schema.
publi0 added 2 commits March 15, 2026 00:01
… guide

- Add t.Parallel() to all test functions for faster execution
- Replace assert with require for setup steps (state.Set, plan.Set)
  so tests fail fast on broken setup instead of cascading failures
- Fix 7 instances of silently ignored state/plan.Set() errors
  (was: _ = state.Set(...), now: properly checked with require)
- Replace hardcoded assert.Len counts in GetResources/GetDataSources
  tests with assert.NotEmpty + loop (less brittle)
- Remove unused getTypeName/getConcreteTypeName helpers
- Update UNIT_TESTING.md with improved examples and new sections
  for Update method, error path testing, and table-driven tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants