|
| 1 | + FreezeGun to TimeMachine Migration Example |
| 2 | + |
| 3 | +This example demonstrates how to use Codegen to automatically migrate test code from FreezeGun to TimeMachine for time mocking. The migration script makes this process simple by handling all the tedious manual updates automatically. |
| 4 | + |
| 5 | +## How the Migration Script Works |
| 6 | + |
| 7 | +The script (`run.py`) automates the entire migration process in a few key steps: |
| 8 | + |
| 9 | +1. **Codebase Loading** |
| 10 | + ```python |
| 11 | + codebase = Codebase.from_repo( |
| 12 | + "getmoto/moto", commit="786a8ada7ed0c7f9d8b04d49f24596865e4b7901") |
| 13 | + ``` |
| 14 | + - Loads your codebase into Codegen's intelligent code analysis engine |
| 15 | + - Provides a simple SDK for making codebase-wide changes |
| 16 | + - Supports specific commit targeting for version control |
| 17 | + |
| 18 | +2. **Test File Detection** |
| 19 | + ```python |
| 20 | + if "tests" not in file.filepath: |
| 21 | + continue |
| 22 | + ``` |
| 23 | + - Automatically identifies test files using Codegen's file APIs |
| 24 | + - Skips non-test files to avoid unnecessary processing |
| 25 | + - Focuses changes where time mocking is most commonly used |
| 26 | + |
| 27 | +3. **Import Updates** |
| 28 | + ```python |
| 29 | + for imp in file.imports: |
| 30 | + if imp.symbol_name and 'freezegun' in imp.source: |
| 31 | + if imp.name == 'freeze_time': |
| 32 | + imp.edit('from time_machine import travel') |
| 33 | + ``` |
| 34 | + - Uses Codegen's import analysis to find and update imports |
| 35 | + - Handles both direct and aliased imports |
| 36 | + - Preserves import structure and formatting |
| 37 | + |
| 38 | +4. **Function Call Transformation** |
| 39 | + ```python |
| 40 | + for fcall in file.function_calls: |
| 41 | + if 'freeze_time' not in fcall.source: |
| 42 | + continue |
| 43 | + # Transform freeze_time to travel with tick=False |
| 44 | + ``` |
| 45 | + - Uses Codegen's function call analysis to find all usages |
| 46 | + - Adds required TimeMachine parameters |
| 47 | + - Maintains existing arguments and formatting |
| 48 | + |
| 49 | +## Why This Makes Migration Easy |
| 50 | + |
| 51 | +1. **Zero Manual Updates** |
| 52 | + - Codegen SDK handles all the file searching and updating |
| 53 | + - No tedious copy-paste work |
| 54 | + |
| 55 | +2. **Consistent Changes** |
| 56 | + - Codegen ensures all transformations follow the same patterns |
| 57 | + - Maintains code style consistency |
| 58 | + |
| 59 | +3. **Safe Transformations** |
| 60 | + - Codegen validates changes before applying them |
| 61 | + - Easy to review and revert if needed |
| 62 | + |
| 63 | +## Common Migration Patterns |
| 64 | + |
| 65 | +### Decorator Usage |
| 66 | +```python |
| 67 | +# FreezeGun |
| 68 | +@freeze_time("2023-01-01") |
| 69 | +def test_function(): |
| 70 | + pass |
| 71 | + |
| 72 | +# Automatically converted to: |
| 73 | +@travel("2023-01-01", tick=False) |
| 74 | +def test_function(): |
| 75 | + pass |
| 76 | +``` |
| 77 | + |
| 78 | +### Context Manager Usage |
| 79 | +```python |
| 80 | +# FreezeGun |
| 81 | +with freeze_time("2023-01-01"): |
| 82 | + # test code |
| 83 | + |
| 84 | +# Automatically converted to: |
| 85 | +with travel("2023-01-01", tick=False): |
| 86 | + # test code |
| 87 | +``` |
| 88 | + |
| 89 | +### Moving Time Forward |
| 90 | +```python |
| 91 | +# FreezeGun |
| 92 | +freezer = freeze_time("2023-01-01") |
| 93 | +freezer.start() |
| 94 | +freezer.move_to("2023-01-02") |
| 95 | +freezer.stop() |
| 96 | + |
| 97 | +# Automatically converted to: |
| 98 | +traveller = travel("2023-01-01", tick=False) |
| 99 | +traveller.start() |
| 100 | +traveller.shift(datetime.timedelta(days=1)) |
| 101 | +traveller.stop() |
| 102 | +``` |
| 103 | + |
| 104 | +## Key Differences to Note |
| 105 | + |
| 106 | +1. **Tick Parameter** |
| 107 | + - TimeMachine requires explicit tick behavior configuration |
| 108 | + - Script automatically adds `tick=False` to match FreezeGun's default behavior |
| 109 | + |
| 110 | +2. **Time Movement** |
| 111 | + - FreezeGun uses `move_to()` with datetime strings |
| 112 | + - TimeMachine uses `shift()` with timedelta objects |
| 113 | + |
| 114 | +3. **Return Values** |
| 115 | + - FreezeGun's decorator returns the freezer object |
| 116 | + - TimeMachine's decorator returns a traveller object |
| 117 | + |
| 118 | +## Running the Migration |
| 119 | + |
| 120 | +```bash |
| 121 | +# Install Codegen |
| 122 | +pip install codegen |
| 123 | +# Run the migration |
| 124 | +python run.py |
| 125 | +``` |
| 126 | + |
| 127 | +## Learn More |
| 128 | + |
| 129 | +- [TimeMachine Documentation](https://github.com/adamchainz/time-machine) |
| 130 | +- [FreezeGun Documentation](https://github.com/spulec/freezegun) |
| 131 | +- [Codegen Documentation](https://docs.codegen.com) |
| 132 | + |
| 133 | +## Contributing |
| 134 | + |
| 135 | +Feel free to submit issues and enhancement requests! |
0 commit comments