@@ -22,17 +22,27 @@ jobs:
2222 id : discover
2323 run : |
2424 # Find all test files in e2e directory
25- TEST_FILES=$(find tests/e2e -name "test_*.py" -type f | sort | jq -R -s -c 'split("\n")[:-1]')
26- echo "test-files=$TEST_FILES" >> $GITHUB_OUTPUT
27- echo "Discovered test files: $TEST_FILES"
25+ E2E_FILES=$(find tests/e2e -name "test_*.py" -type f | sort | jq -R -s -c 'split("\n")[:-1]')
26+ echo "e2e-test-files=$E2E_FILES" >> $GITHUB_OUTPUT
27+ echo "Discovered E2E test files: $E2E_FILES"
28+
29+ # Find all test files in unit directory
30+ UNIT_FILES=$(find tests/unit -name "test_*.py" -type f | sort | jq -R -s -c 'split("\n")[:-1]')
31+ echo "unit-test-files=$UNIT_FILES" >> $GITHUB_OUTPUT
32+ echo "Discovered unit test files: $UNIT_FILES"
33+
34+ # Find all test files in common directory
35+ COMMON_FILES=$(find tests/e2e/common -name "*.py" -type f | grep -v __init__ | sort | jq -R -s -c 'split("\n")[:-1]')
36+ echo "common-test-files=$COMMON_FILES" >> $GITHUB_OUTPUT
37+ echo "Discovered common test files: $COMMON_FILES"
2838
2939 e2e-tests :
3040 runs-on : ubuntu-latest
3141 environment : azure-prod
3242 needs : discover-tests
3343 strategy :
3444 matrix :
35- test_file : ${{ fromJson(needs.discover-tests.outputs.test-files) }}
45+ test_file : ${{ fromJson(needs.discover-tests.outputs.e2e- test-files) }}
3646 mode : ["thrift", "sea"]
3747 env :
3848 DATABRICKS_SERVER_HOSTNAME : ${{ secrets.DATABRICKS_HOST }}
@@ -125,9 +135,169 @@ jobs:
125135 coverage-*-${{ matrix.mode }}.xml
126136 if-no-files-found : warn
127137
138+ unit-tests :
139+ runs-on : ubuntu-latest
140+ needs : discover-tests
141+ strategy :
142+ matrix :
143+ test_file : ${{ fromJson(needs.discover-tests.outputs.unit-test-files) }}
144+ steps :
145+ - name : Check out repository
146+ uses : actions/checkout@v4
147+ with :
148+ fetch-depth : 0
149+ ref : ${{ github.event.pull_request.head.ref || github.ref_name }}
150+ repository : ${{ github.event.pull_request.head.repo.full_name || github.repository }}
151+
152+ - name : Set up python
153+ id : setup-python
154+ uses : actions/setup-python@v5
155+ with :
156+ python-version : " 3.10"
157+
158+ - name : Install Poetry
159+ uses : snok/install-poetry@v1
160+ with :
161+ virtualenvs-create : true
162+ virtualenvs-in-project : true
163+ installer-parallel : true
164+
165+ - name : Load cached venv
166+ id : cached-poetry-dependencies
167+ uses : actions/cache@v4
168+ with :
169+ path : .venv
170+ key : venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ github.event.repository.name }}-${{ hashFiles('**/poetry.lock') }}
171+
172+ - name : Install dependencies
173+ if : steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
174+ run : poetry install --no-interaction --no-root
175+
176+ - name : Install library
177+ run : poetry install --no-interaction --all-extras
178+
179+ - name : Run unit tests with coverage
180+ run : |
181+ TEST_NAME=$(basename "${{ matrix.test_file }}" .py)
182+ COVERAGE_FILE="coverage-${TEST_NAME}-unit.xml"
183+ COVERAGE_DATA="coverage-data-${TEST_NAME}-unit"
184+ echo "TEST_NAME=$TEST_NAME" >> $GITHUB_ENV
185+
186+ # Clean any previous coverage data to avoid conflicts
187+ rm -f .coverage*
188+
189+ echo "Running unit tests with coverage..."
190+ poetry run pytest "${{ matrix.test_file }}" --cov=src --cov-report=xml:$COVERAGE_FILE --cov-report=term -v
191+
192+ # Save coverage data with unique name
193+ if [ -f ".coverage" ]; then
194+ mv .coverage "$COVERAGE_DATA"
195+ echo "Coverage data saved as $COVERAGE_DATA"
196+ else
197+ # Create minimal coverage file for cases where no tests run
198+ poetry run coverage erase
199+ poetry run coverage run --source=src -m pytest --version > /dev/null 2>&1 || true
200+ if [ -f ".coverage" ]; then
201+ mv .coverage "$COVERAGE_DATA"
202+ else
203+ touch "$COVERAGE_DATA"
204+ fi
205+ echo "Created minimal coverage file as $COVERAGE_DATA"
206+ fi
207+
208+ - name : Upload coverage artifact
209+ uses : actions/upload-artifact@v4
210+ if : always()
211+ with :
212+ name : coverage-${{ env.TEST_NAME }}-unit
213+ path : |
214+ coverage-data-*
215+ coverage-*-unit.xml
216+ if-no-files-found : warn
217+
218+ common-tests :
219+ runs-on : ubuntu-latest
220+ needs : discover-tests
221+ strategy :
222+ matrix :
223+ test_file : ${{ fromJson(needs.discover-tests.outputs.common-test-files) }}
224+ steps :
225+ - name : Check out repository
226+ uses : actions/checkout@v4
227+ with :
228+ fetch-depth : 0
229+ ref : ${{ github.event.pull_request.head.ref || github.ref_name }}
230+ repository : ${{ github.event.pull_request.head.repo.full_name || github.repository }}
231+
232+ - name : Set up python
233+ id : setup-python
234+ uses : actions/setup-python@v5
235+ with :
236+ python-version : " 3.10"
237+
238+ - name : Install Poetry
239+ uses : snok/install-poetry@v1
240+ with :
241+ virtualenvs-create : true
242+ virtualenvs-in-project : true
243+ installer-parallel : true
244+
245+ - name : Load cached venv
246+ id : cached-poetry-dependencies
247+ uses : actions/cache@v4
248+ with :
249+ path : .venv
250+ key : venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ github.event.repository.name }}-${{ hashFiles('**/poetry.lock') }}
251+
252+ - name : Install dependencies
253+ if : steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
254+ run : poetry install --no-interaction --no-root
255+
256+ - name : Install library
257+ run : poetry install --no-interaction --all-extras
258+
259+ - name : Run common tests with coverage
260+ run : |
261+ TEST_NAME=$(basename "${{ matrix.test_file }}" .py)
262+ COVERAGE_FILE="coverage-${TEST_NAME}-common.xml"
263+ COVERAGE_DATA="coverage-data-${TEST_NAME}-common"
264+ echo "TEST_NAME=$TEST_NAME" >> $GITHUB_ENV
265+
266+ # Clean any previous coverage data to avoid conflicts
267+ rm -f .coverage*
268+
269+ echo "Running common tests with coverage..."
270+ poetry run pytest "${{ matrix.test_file }}" --cov=src --cov-report=xml:$COVERAGE_FILE --cov-report=term -v
271+
272+ # Save coverage data with unique name
273+ if [ -f ".coverage" ]; then
274+ mv .coverage "$COVERAGE_DATA"
275+ echo "Coverage data saved as $COVERAGE_DATA"
276+ else
277+ # Create minimal coverage file for cases where no tests run
278+ poetry run coverage erase
279+ poetry run coverage run --source=src -m pytest --version > /dev/null 2>&1 || true
280+ if [ -f ".coverage" ]; then
281+ mv .coverage "$COVERAGE_DATA"
282+ else
283+ touch "$COVERAGE_DATA"
284+ fi
285+ echo "Created minimal coverage file as $COVERAGE_DATA"
286+ fi
287+
288+ - name : Upload coverage artifact
289+ uses : actions/upload-artifact@v4
290+ if : always()
291+ with :
292+ name : coverage-${{ env.TEST_NAME }}-common
293+ path : |
294+ coverage-data-*
295+ coverage-*-common.xml
296+ if-no-files-found : warn
297+
128298 merge-coverage :
129299 runs-on : ubuntu-latest
130- needs : [e2e-tests]
300+ needs : [e2e-tests, unit-tests, common-tests ]
131301 steps :
132302 - name : Check out repository
133303 uses : actions/checkout@v4
0 commit comments