Announcing SwiftQC: A Feature-Rich Testing Framework for Swift 6 with Stateful & Parallel Capabilities

Hey everyone,

I'm excited to introduce SwiftQC, a property-based testing framework I built specifically for Swift 6+ and modern Swift development.

Repository: https://github.com/Aristide021/SwiftQC
Documentation: Complete guides and examples


Why Property-Based Testing?

As developers, we usually write tests by coming up with specific inputs and checking the outputs. SwiftQC automatically generates hundreds of test cases, and when failures occur, intelligently shrinks them to the minimal counterexample, often revealing edge cases you'd never think to test manually.


What SwiftQC Brings To The Table

Complete Stateful Testing Engine

Confidently test complex user flows and stateful APIs.** SwiftQC's stateful engine lets you model your system's behavior, then automatically generates sequences of commands to find elusive, state-related bugs. When a test fails, its powerful command sequence shrinker pinpoints the minimal steps needed to reproduce the error, saving you hours of debugging.

Concurrent System Verification

Built-in parallel testing runner helps discover race conditions and concurrency bugs by executing commands concurrently and detecting divergences from expected behavior.

Elegant, Composable Design

  • Sendable-first architecture built for Swift 6+ concurrency
  • Seamless integration with Swift Testing's issue reporting system
  • Built on proven foundations - leverages PointFree's excellent swift-gen for composable generators
  • Ergonomic Arbitrary protocol makes most tests incredibly concise

Usage

Basic Property Testing:

import SwiftQC
import Testing

@Test
func additionIsCommutative() async {
  await forAll("Integer addition is commutative") { (a: Int, b: Int) in
    #expect(a + b == b + a)
  }
}

Custom Types:

struct Point: Arbitrary, Sendable, Equatable {
    let x: Int, y: Int
    
    static var gen: Gen<Point> {
        zip(Int.gen, Int.gen).map(Point.init)
    }
    
    static var shrinker: any Shrinker<Point> {
        Shrinkers.map(
            from: Shrinkers.tuple(Shrinkers.int, Shrinkers.int),
            transform: Point.init,
            reverse: { ($0.x, $0.y) }
        )
    }
}

@Test
func pointDistanceIsCommutative() async {
    await forAll("Distance calculation is commutative") { (p1: Point, p2: Point) in
        #expect(distance(p1, p2) == distance(p2, p1))
    }
}

Stateful Testing:

// Define your state model
struct CounterModel: StateModel {
    typealias State = Int
    typealias SUT = MyCounter
    // ... command generation, state transitions, etc.
}

@Test
func counterMaintainsConsistency() async {
    let result = await stateful(
        "Counter behaves according to model",
        sutFactory: { MyCounter() }
    )
    // SwiftQC handles command sequence generation, execution,
    // divergence detection, and automatic shrinking
}

Rich Ecosystem Support

SwiftQC provides Arbitrary conformances for extensive Swift standard library coverage:

  • Numeric types: All integer and floating-point variants, including Decimal and CGFloat
  • Text processing: String, Character, Unicode.Scalar
  • Collections: Array, Dictionary, Set, Optional, Result
  • Foundation types: Date, Data, UUID, and more

Getting Started

Installation:

// Package.swift
.package(url: "https://github.com/Aristide021/SwiftQC.git", from: "1.0.0")

Requirements:

  • Swift 6.0+
  • Platforms: macOS 12+, iOS 13+, tvOS 13+, watchOS 6+
  • Works with both Swift Testing and XCTest

Explore the Examples:

Each example is a complete Swift package you can run immediately:
cd Examples/BasicUsage && swift test


Community & Feedback

I would greatly appreciate your feedback, contributions, and real-world testing. Please try it out and share your thoughts, whether through GitHub issues, discussions, or the forums.

7 Likes

This looks amazing, I'm very glad to see more libraries supporting property-based testing in Swift!

Minor nit: for some reason LICENSE file is not detected as Apache 2.0 on GitHub? Usually it's best to use their auto-generated template for detection to work, and any notes to be added in README.md or separate files.

2 Likes

Thanks! Can't wait to see how people will utilize this for testing stateful and parallel code in Swift.

Thanks for the heads up on the LICENSE detection! I just fixed it, should show up as Apache 2.0 now.

Appreciate the feedback!

1 Like

Interesting!

Could probably drop the dependency on swift-atomics and use the built-in ones as you target a modern toolchain only?