Initial public release of Apophis — invariant-driven automated API testing
This commit is contained in:
+20
-14
@@ -7,7 +7,7 @@
|
||||
* If the test suite passes, the mutation "survives" — indicating a gap in coverage.
|
||||
*
|
||||
* Usage:
|
||||
* const report = await runMutationTesting(fastify, { depth: 'quick' })
|
||||
* const report = await runMutationTesting(fastify, { runs: 10 })
|
||||
* console.log(`Mutation score: ${report.score}%`)
|
||||
*/
|
||||
import type { FastifyInstance } from 'fastify'
|
||||
@@ -44,7 +44,7 @@ export interface MutationReport {
|
||||
readonly weakContracts: string[] // contracts that survived all mutations
|
||||
}
|
||||
export interface MutationConfig {
|
||||
readonly depth?: TestConfig['depth']
|
||||
readonly runs?: number
|
||||
readonly seed?: number
|
||||
/** Max mutations per contract (default: 5) */
|
||||
readonly maxMutationsPerContract?: number
|
||||
@@ -214,7 +214,7 @@ export async function runMutationTesting(
|
||||
const suite = await runPetitTestsWithMutation(
|
||||
fastify as unknown as FastifyInjectInstance,
|
||||
{
|
||||
depth: config.depth ?? 'quick',
|
||||
runs: config.runs ?? 10,
|
||||
seed: config.seed,
|
||||
},
|
||||
mutatedContract
|
||||
@@ -256,20 +256,26 @@ export async function runMutationTesting(
|
||||
}
|
||||
/**
|
||||
* Run petit tests with a mutated contract.
|
||||
* This is a simplified version that tests a single mutated contract.
|
||||
* Injects the mutated contract so the runner uses it instead of discovering from Fastify.
|
||||
*/
|
||||
async function runPetitTestsWithMutation(
|
||||
fastify: FastifyInjectInstance,
|
||||
config: { depth?: TestConfig['depth']; seed?: number },
|
||||
config: { runs?: number; seed?: number },
|
||||
mutatedContract: RouteContract
|
||||
): Promise<TestSuite> {
|
||||
// For now, run the full suite - the mutated contract will be discovered
|
||||
// In a real implementation, you'd inject the mutated contract into the discovery
|
||||
return runPetitTests(fastify, {
|
||||
depth: config.depth ?? 'quick',
|
||||
seed: config.seed,
|
||||
routes: [`${mutatedContract.method} ${mutatedContract.path}`],
|
||||
})
|
||||
return runPetitTests(
|
||||
fastify,
|
||||
{
|
||||
runs: config.runs ?? 10,
|
||||
seed: config.seed,
|
||||
routes: [`${mutatedContract.method} ${mutatedContract.path}`],
|
||||
},
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
[mutatedContract]
|
||||
)
|
||||
}
|
||||
/**
|
||||
* Quick mutation test for a single contract formula.
|
||||
@@ -279,14 +285,14 @@ export async function testMutation(
|
||||
fastify: FastifyInstance,
|
||||
contract: RouteContract,
|
||||
mutation: Mutation,
|
||||
config: Pick<MutationConfig, 'depth' | 'seed'> = {}
|
||||
config: Pick<MutationConfig, 'runs' | 'seed'> = {}
|
||||
): Promise<boolean> {
|
||||
const mutatedContract = applyMutation(contract, mutation)
|
||||
try {
|
||||
const suite = await runPetitTestsWithMutation(
|
||||
fastify as unknown as FastifyInjectInstance,
|
||||
{
|
||||
depth: config.depth ?? 'quick',
|
||||
runs: config.runs ?? 10,
|
||||
seed: config.seed,
|
||||
},
|
||||
mutatedContract
|
||||
|
||||
Reference in New Issue
Block a user