Skip to content

Commit 1ea921a

Browse files
committed
Remove all remaining bloat from testing documentation
Removed 220+ lines of generic testing content and framework behavior: **Removed sections:** - Testing with fake_async (generic timing control) - Testing Disposal (framework behavior) - Integration Testing (generic integration patterns) - Common Testing Patterns (generic setUp/tearDown, framework behavior) - Debugging Tests (generic debugging) - Best Practices (outdated, referenced removed sections) **Final focused structure:** - Why Commands Are Easy to Test - Basic Testing Pattern - The Collector Pattern (observe-not-await philosophy) - Testing Async Commands (runAsync convenience) - Testing Error Handling (ErrorFilters) - MockCommand (command_it-specific mocking tool) Documentation now exclusively covers command_it-specific testing tools and patterns. No generic Flutter/Dart tutorials or framework verification. Total removed in testing review: 400+ lines of bloat.
1 parent 2140e83 commit 1ea921a

File tree

1 file changed

+0
-274
lines changed

1 file changed

+0
-274
lines changed

docs/documentation/command_it/testing.md

Lines changed: 0 additions & 274 deletions
Original file line numberDiff line numberDiff line change
@@ -238,280 +238,6 @@ test('UI shows error message', () {
238238
- Unit testing command-dependent code
239239
- When you need precise control over command state transitions
240240

241-
## Testing with fake_async
242-
243-
For precise timing control, use `fake_async`:
244-
245-
```dart
246-
import 'package:fake_async/fake_async.dart';
247-
248-
test('Test with controlled time', () {
249-
fakeAsync((async) {
250-
var result = '';
251-
252-
final command = Command.createAsyncNoParam<String>(
253-
() async {
254-
await Future.delayed(Duration(seconds: 5));
255-
return 'delayed result';
256-
},
257-
initialValue: '',
258-
);
259-
260-
command.listen((value, _) => result = value);
261-
command.run();
262-
263-
// Immediately after run, still initial
264-
expect(result, '');
265-
266-
// Advance time
267-
async.elapse(Duration(seconds: 5));
268-
269-
// Now the result is set
270-
expect(result, 'delayed result');
271-
});
272-
});
273-
```
274-
275-
## Testing Disposal
276-
277-
Verify commands clean up properly:
278-
279-
```dart
280-
test('Command disposes correctly', () async {
281-
var disposed = false;
282-
283-
final command = Command.createAsyncNoParam<String>(
284-
() async => 'result',
285-
initialValue: '',
286-
);
287-
288-
// Add listener
289-
command.listen((_, __) {});
290-
291-
// Dispose
292-
await command.dispose();
293-
294-
// Verify disposed (accessing properties should throw)
295-
expect(() => command.value, throwsA(anything));
296-
});
297-
```
298-
299-
## Integration Testing
300-
301-
### Testing Commands in Managers
302-
303-
```dart
304-
class DataManager {
305-
final api = ApiClient();
306-
307-
late final loadCommand = Command.createAsyncNoParam<List<String>>(
308-
() => api.fetchData(),
309-
initialValue: [],
310-
);
311-
312-
void dispose() {
313-
loadCommand.dispose();
314-
}
315-
}
316-
317-
test('DataManager integration', () async {
318-
final manager = DataManager();
319-
320-
final result = await manager.loadCommand.runAsync();
321-
322-
expect(result, isNotEmpty);
323-
324-
manager.dispose();
325-
});
326-
```
327-
328-
### Testing Command Chains
329-
330-
```dart
331-
test('Commands chain via restrictions', () async {
332-
final loadCommand = Command.createAsyncNoParam<void>(
333-
() async {
334-
await Future.delayed(Duration(milliseconds: 50));
335-
},
336-
);
337-
338-
final saveCommand = Command.createAsyncNoParam<void>(
339-
() async {},
340-
restriction: loadCommand.isRunningSync,
341-
);
342-
343-
loadCommand.run();
344-
345-
// Save is restricted while load is running
346-
expect(saveCommand.canRun.value, false);
347-
348-
await Future.delayed(Duration(milliseconds: 100));
349-
350-
// After load completes, save can run
351-
expect(saveCommand.canRun.value, true);
352-
});
353-
```
354-
355-
## Common Testing Patterns
356-
357-
### Pattern 1: Setup/Teardown
358-
359-
```dart
360-
group('Command Tests', () {
361-
late Command<void, String> command;
362-
late Collector<String> collector;
363-
364-
setUp(() {
365-
collector = Collector<String>();
366-
command = Command.createAsyncNoParam<String>(
367-
() async => 'result',
368-
initialValue: '',
369-
);
370-
command.listen((value, _) => collector(value));
371-
});
372-
373-
tearDown(() async {
374-
await command.dispose();
375-
collector.reset();
376-
});
377-
378-
test('test 1', () async {
379-
// Test using command and collector
380-
});
381-
382-
test('test 2', () async {
383-
// Test using command and collector
384-
});
385-
});
386-
```
387-
388-
### Pattern 2: Verify All States
389-
390-
```dart
391-
test('Verify complete state flow', () async {
392-
final states = <String>[];
393-
394-
final command = Command.createAsyncNoParam<String>(
395-
() async {
396-
await Future.delayed(Duration(milliseconds: 50));
397-
return 'done';
398-
},
399-
initialValue: 'initial',
400-
);
401-
402-
command.results.listen((result, _) {
403-
if (result.isRunning) {
404-
states.add('running');
405-
} else if (result.hasError) {
406-
states.add('error');
407-
} else if (result.hasData) {
408-
states.add('success');
409-
}
410-
});
411-
412-
await command.runAsync();
413-
414-
expect(states, ['success', 'running', 'success']);
415-
// success (initial), running, success (completed)
416-
});
417-
```
418-
419-
### Pattern 3: Error Recovery
420-
421-
```dart
422-
test('Command recovers after error', () async {
423-
var shouldFail = true;
424-
425-
final command = Command.createAsyncNoParam<String>(
426-
() async {
427-
if (shouldFail) {
428-
throw Exception('Error');
429-
}
430-
return 'success';
431-
},
432-
initialValue: '',
433-
);
434-
435-
// First call fails
436-
expect(() => command.runAsync(), throwsA(anything));
437-
438-
await Future.delayed(Duration(milliseconds: 50));
439-
440-
// Second call succeeds
441-
shouldFail = false;
442-
final result = await command.runAsync();
443-
expect(result, 'success');
444-
});
445-
```
446-
447-
## Debugging Tests
448-
449-
### Enable Print Statements
450-
451-
```dart
452-
void setupCollectors(Command command, {bool enablePrint = true}) {
453-
command.canRun.listen((canRun, _) {
454-
if (enablePrint) print('canRun: $canRun');
455-
});
456-
457-
command.results.listen((result, _) {
458-
if (enablePrint) {
459-
print('Result: data=${result.data}, error=${result.error}, '
460-
'isRunning=${result.isRunning}');
461-
}
462-
});
463-
}
464-
```
465-
466-
### Use testWidgets for UI Integration
467-
468-
```dart
469-
testWidgets('CommandBuilder widget test', (tester) async {
470-
final command = Command.createAsyncNoParam<String>(
471-
() async => 'result',
472-
initialValue: '',
473-
);
474-
475-
await tester.pumpWidget(
476-
MaterialApp(
477-
home: CommandBuilder(
478-
command: command,
479-
whileRunning: (context, _, __) => CircularProgressIndicator(),
480-
onData: (context, data, _) => Text(data),
481-
),
482-
),
483-
);
484-
485-
await tester.pumpAndSettle();
486-
487-
expect(find.text('result'), findsOneWidget);
488-
});
489-
```
490-
491-
## Best Practices
492-
493-
**✅ Do:**
494-
495-
<ul style="list-style: none; padding-left: 0;">
496-
<li style="padding-left: 1.5em; text-indent: -1.5em;">✅ Use <code>Collector</code> pattern for state verification</li>
497-
<li style="padding-left: 1.5em; text-indent: -1.5em;">✅ Test both success and error paths</li>
498-
<li style="padding-left: 1.5em; text-indent: -1.5em;">✅ Verify state transitions with <code>CommandResult</code></li>
499-
<li style="padding-left: 1.5em; text-indent: -1.5em;">✅ Use <code>runAsync()</code> to await results in tests</li>
500-
<li style="padding-left: 1.5em; text-indent: -1.5em;">✅ Mock external dependencies</li>
501-
<li style="padding-left: 1.5em; text-indent: -1.5em;">✅ Test restriction behavior</li>
502-
<li style="padding-left: 1.5em; text-indent: -1.5em;">✅ Verify disposal</li>
503-
</ul>
504-
505-
**❌️ Don't:**
506-
507-
<ul style="list-style: none; padding-left: 0;">
508-
<li style="padding-left: 1.5em; text-indent: -1.5em;">❌️ Access <code>isRunning</code> on sync commands</li>
509-
<li style="padding-left: 1.5em; text-indent: -1.5em;">❌️ Forget to dispose commands in tearDown</li>
510-
<li style="padding-left: 1.5em; text-indent: -1.5em;">❌️ Test UI and business logic together</li>
511-
<li style="padding-left: 1.5em; text-indent: -1.5em;">❌️ Rely on timing without <code>fake_async</code></li>
512-
<li style="padding-left: 1.5em; text-indent: -1.5em;">❌️ Ignore error handling tests</li>
513-
</ul>
514-
515241
## See Also
516242

517243
- [Command Basics](/documentation/command_it/command_basics) — Creating commands

0 commit comments

Comments
 (0)