Skip to content

Conversation

@MaryGao
Copy link
Member

@MaryGao MaryGao commented Jul 27, 2025

fixes #3247 #3371 #3345

Mary Gao and others added 8 commits July 27, 2025 16:58
- Added modular test generation similar to samples
- Test names use sample description logic for consistency
- Clean test names without trailing dots
- Proper vitest/mocha framework support based on module type
- Azure Identity integration for ARM clients
- Generated test utilities including recordedClient.ts
- Support for both single and multiple client scenarios
- Unique test names including function names for multiple examples

Generated 7 operation test files with professional naming:
- assign role to the data product for dataProductsAddUserRoleMaximumSetGen
- create data product resource for dataProductsCreateMaximumSetGen
- delete data product resource for dataProductsDeleteMaximumSetGen
- generate sas token for storage account for dataProductsGenerateStorageAccountSasTokenMaximumSetGen
- list data products by resource group for dataProductsListByResourceGroupMaximumSetGenGeneratedByMinimumSetRuleMinimumSetGen
- initiate key rotation on Data Product for dataProductsRotateKeyMaximumSetGen
- update data product resource for dataProductsUpdateMaximumSetGen
Enhanced test generation to include response assertions that validate response values against expected values from examples:

- Added generateResponseAssertions() function
- Added generateAssertionsForValue() for recursive validation
- Support for string, number, boolean, array, model, dict, null, union types
- Proper handling of TypeSpec SDK numeric response indices
- Validates key response properties with strictEqual checks
- Array length and item validation
- Model/object property validation up to 3 levels deep

Generated tests now include comprehensive response validation like:
assert.strictEqual(result.properties.resourceGuid, expected_value)
assert.strictEqual(result.properties.provisioningState, expected_value)
assert.ok(Array.isArray(result.dataTypeScope))

This ensures tests validate both API success and response content.
- Added 4 passing unit test scenarios for test generation:
  - basicOperationTest: Tests simple GET operation with response assertions
  - pagingOperationTest: Tests paging operations with array response validation
  - moduleTypeTest: Tests different import styles for ESM vs CommonJS
  - complexResponseTest: Tests nested object response assertions
- Added emitTestsFromTypeSpec function to test/util/emitUtil.ts
- Enhanced scenarios.spec.ts with 'tests' output block type
- Improved test output formatting with proper file separation
- All test scenarios validate comprehensive response assertions
- Tests follow same pattern as existing samples scenarios
- Fix formatting issues in emitTests.ts (whitespace and comment styles)
- Update scenarios.spec.ts with better test file handling and formatting fixes
- Refresh test scenario files with updated expected outputs:
  - basicOperationTest.md: Updated with improved test structure
  - complexResponseTest.md: Updated response assertion patterns
  - moduleTypeTest.md: Updated with proper module import handling
  - pagingOperationTest.md: Updated paging operation test patterns
  - voidOperationTest.md: Updated void operation test handling

All tests passing with SCENARIOS_UPDATE=true refresh
### LRO (Long Running Operations) Support:
- Add detection for LRO operations (method.kind === 'lro' || method.kind === 'lropaging')
- Generate proper poller pattern: 'const poller = await client.method()' followed by 'const result = await poller.pollUntilDone()'
- Add comprehensive LRO test scenario (lroOperationTest.md) with ArmResourceCreateOrReplaceAsync example
- Include proper response assertions on the final LRO result

### Paging Test Improvements:
- Create dedicated generatePagingResponseAssertions() function
- Fix incorrect paging assertions that were checking resArray[0].value instead of resArray directly
- Now correctly asserts on collected results length and individual item properties
- Updated pagingOperationTest.md with proper assertions

### Test Coverage Enhancement:
- Fixed void operation test (voidOperationTest.md) to properly handle LRO delete operations
- All 6 test scenarios now passing: basic, complex, module, paging, void, and LRO operations

### Technical Improvements:
- Better separation of concerns between regular, paging, and LRO test generation
- Proper understanding of how paging iteration works vs response structure
- Correct LRO poller pattern following Azure SDK conventions
@MaryGao MaryGao changed the title Generate test modular Test generation in Modular Jul 30, 2025
MaryGao and others added 18 commits July 31, 2025 16:52
- Created shared utility module sampleTestHelpers.ts to reduce code duplication
- Extracted common functions: buildParameterValueMap, prepareCommonValue, getCredentialSampleValue, getCredentialTestValue, serializeExampleValue
- Unified CommonValue interface for both samples and tests
- Refactored emitSamples.ts and emitTests.ts to use shared utilities
- Eliminated ~200+ lines of duplicate code while maintaining functionality
- All 388 modular unit tests continue to pass
…tilities

- Created comprehensive sampleTestHelpers.ts module with shared utilities
- Extracted common functions: prepareCommonParameters, iterateClientsAndMethods, generateMethodCall, createSourceFile, generateAssertionsForValue, generateResponseAssertions
- Reduced code duplication by ~200+ lines across emit files
- Enhanced test vs sample differentiation (env variables for tests, example values for samples)
- Improved maintainability with unified parameter preparation and assertion generation
- All 388 modular unit tests passing after refactoring

Breaking down the previous monolithic emit functions into:
1. Common parameter handling logic shared between samples and tests
2. Unified client/method iteration patterns
3. Shared assertion generation for response validation
4. Consistent source file creation and import handling
5. Better separation of concerns between sample and test generation

This refactoring eliminates significant code duplication while maintaining 100% test compatibility.
@MaryGao MaryGao changed the title Test generation in Modular Test Generation in Modular Aug 28, 2025
@MaryGao MaryGao marked this pull request as ready for review September 8, 2025 05:12
@qiaozha qiaozha added the p0 priority 0 label Sep 10, 2025
@lirenhe lirenhe requested a review from Copilot October 29, 2025 08:19
Copy link
Contributor

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 experimental test generation functionality for the TypeSpec TypeScript emitter. It adds the ability to automatically generate test files from TypeSpec examples, similar to the existing sample generation feature, with proper test recorder integration and response assertions.

Key Changes

  • Added new test generation infrastructure with emitTests.ts and shared helper utilities in exampleValueHelpers.ts
  • Introduced static test helper for recorder client setup (recordedClient.ts)
  • Added extensive unit test scenarios covering parameters, responses, and various operation types
  • Updated the binder to handle test-specific helper files

Reviewed Changes

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

Show a summary per file
File Description
packages/typespec-ts/src/modular/emitTests.ts New file implementing test generation logic with vitest integration
packages/typespec-ts/src/modular/helpers/exampleValueHelpers.ts New shared utilities for both samples and tests, including parameter processing and assertion generation
packages/typespec-ts/src/modular/emitSamples.ts Refactored to use shared helpers from exampleValueHelpers.ts
packages/typespec-ts/src/modular/external-dependencies.ts Added AzureTestDependencies for vitest and test-recorder imports
packages/typespec-ts/src/modular/static-helpers-metadata.ts Added CreateRecorderHelpers metadata
packages/typespec-ts/static/test-helpers/recordedClient.ts New static helper for test recorder setup
packages/typespec-ts/src/framework/load-static-helpers.ts Enhanced to load test helpers from test-helpers directory
packages/typespec-ts/src/framework/hooks/binder.ts Updated to clean unused helper files in test directories
packages/typespec-ts/src/lib.ts Added experimental-generate-test-files option to schema
packages/typespec-ts/src/index.ts Integrated test generation into emit pipeline
packages/typespec-ts/test/util/testUtil.ts Added test dependencies to test utilities
packages/typespec-ts/test/util/emitUtil.ts Added emitTestsFromTypeSpec helper function
packages/typespec-ts/test/modularUnit/scenarios.spec.ts Added test generation support to scenario testing
packages/typespec-ts/test/modularUnit/scenarios/test/**/*.md New test scenario files covering various parameter and operation types
packages/typespec-ts/test-next/integration/load-static-files.test.ts Updated expected file count for additional helper file
Comments suppressed due to low confidence (2)

packages/typespec-ts/src/framework/load-static-helpers.ts:1

  • Typo in comment: 'normalizae' should be 'normalize' in the comment on line 324.
import { readdir, stat, readFile } from "fs/promises";

packages/typespec-ts/src/framework/load-static-helpers.ts:1

  • Typo in comment: 'normalizae' should be 'normalize'.
import { readdir, stat, readFile } from "fs/promises";

return {
...defaultSetting,
value: `{ getToken: async () => {
return { token: "INPUT_YOUR_TOKEN_HERE", expiresOnTimestamp: now() }; } }`
Copy link

Copilot AI Oct 29, 2025

Choose a reason for hiding this comment

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

The function now() is undefined. Should be Date.now() for the timestamp.

Suggested change
return { token: "INPUT_YOUR_TOKEN_HERE", expiresOnTimestamp: now() }; } }`
return { token: "INPUT_YOUR_TOKEN_HERE", expiresOnTimestamp: Date.now() }; } }`

Copilot uses AI. Check for mistakes.
Comment on lines +163 to +167
value: `{
getToken: async () => {
return { token: "INPUT_YOUR_TOKEN_HERE", expiresOnTimestamp: Date.now() };
}
} `
Copy link

Copilot AI Oct 29, 2025

Choose a reason for hiding this comment

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

[nitpick] Inconsistent formatting: this credential value has extra spaces and different indentation compared to the sample version on line 120-122. Consider using the same formatting for both.

Suggested change
value: `{
getToken: async () => {
return { token: "INPUT_YOUR_TOKEN_HERE", expiresOnTimestamp: Date.now() };
}
} `
value: `{ getToken: async () => ({ token: "INPUT_YOUR_TOKEN_HERE", expiresOnTimestamp: Date.now() }) }`

Copilot uses AI. Check for mistakes.

${beforeEachType}(async function(ctx) {
recorder = await ${createRecorderHelper}(ctx);
${clientParameterDefs.join("\n")}
Copy link

Copilot AI Oct 29, 2025

Choose a reason for hiding this comment

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

The clientParameterDefs array elements are not being indented when joined. This will cause the generated code to have inconsistent indentation. Consider adding proper indentation: ${clientParameterDefs.join('\\n ')}

Suggested change
${clientParameterDefs.join("\n")}
${clientParameterDefs.join("\n ")}

Copilot uses AI. Check for mistakes.
Comment on lines +571 to +576
const assertions: string[] = [];

// Prevent infinite recursion for deeply nested objects
if (currentDepth >= maxDepth) {
return assertions;
}
Copy link

Copilot AI Oct 29, 2025

Choose a reason for hiding this comment

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

The function generateAssertionsForValue has complex recursive logic with a maxDepth parameter, but lacks a JSDoc comment explaining the purpose of this parameter, the recursion depth limit, and when it would be hit. Consider adding comprehensive documentation.

Copilot uses AI. Check for mistakes.
@MaryGao
Copy link
Member Author

MaryGao commented Oct 29, 2025

@jiaodi Could you help resolve the conflicts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

p0 priority 0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[sample generation] Type 'string' is not assignable to type 'Uint8Array'

4 participants