diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml new file mode 100644 index 0000000..3691eca --- /dev/null +++ b/.github/workflows/unit-tests.yml @@ -0,0 +1,48 @@ +# taken from https://github.com/e-mission/e-mission-server/blob/master/.github/workflows/test-with-manual-install.yml + +name: unit-tests + +# Controls when the action will run. Triggers the workflow on push or pull request +on: + push: + pull_request: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + test-pytest: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Run setup.sh + shell: bash -l {0} + run: | + source bin/setup.sh + + - name: Run pytest + shell: bash -l {0} + run: | + source bin/run_pytest.sh + + test-jest: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: '20' + + - name: Run setup.sh + shell: bash -l {0} + run: | + source bin/setup.sh + + - name: Run jest tests + shell: bash -l {0} + run: | + source bin/run_jest.sh diff --git a/README.md b/README.md index 4dc3ab1..b1f891d 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This repository uses the [Transcrypt](https://www.transcrypt.org/) library to co ## Setup -``` +```bash . bin/setup.sh ``` @@ -126,3 +126,7 @@ There may be testing scenarios that must significantly diverge between Python an ```bash . bin/run_jest.sh ``` + +### GitHub Actions + +The unit tests also run via an Actions workflow, which executes both `run_pytest.sh` and `run_jest.sh` on each commit or PR to `master`. diff --git a/bin/compile_to_js.sh b/bin/compile_to_js.sh old mode 100644 new mode 100755 diff --git a/bin/run_jest.sh b/bin/run_jest.sh old mode 100644 new mode 100755 diff --git a/bin/run_pytest.sh b/bin/run_pytest.sh old mode 100644 new mode 100755 diff --git a/bin/setup.sh b/bin/setup.sh old mode 100644 new mode 100755 index d451d47..754218e --- a/bin/setup.sh +++ b/bin/setup.sh @@ -11,9 +11,9 @@ rm -rf e-mission-server # determine platform if [[ "$OSTYPE" == "linux-gnu"* ]]; then - TARGET_PLATFORM="linux" + TARGET_PLATFORM="Linux-x86_64" elif [[ "$OSTYPE" == "darwin"* ]]; then - TARGET_PLATFORM="mac" + TARGET_PLATFORM="MacOSX-x86_64" else echo "Unsupported platform $OSTYPE" exit 1 diff --git a/test/__testing.py b/test/__testing.py index 941db0b..7b88627 100644 --- a/test/__testing.py +++ b/test/__testing.py @@ -12,11 +12,13 @@ def expectEqual(a, b): ?''' -def expectAlmostEqual(a, b, delta=0.001): - assert abs(a - b) < delta # __: skip +# __pragma__('kwargs') +def expectAlmostEqual(a, b, places=3): + assert abs(a - b) < (.5 / 10 ** places) # __: skip '''? - expect(a).toBeCloseTo(b, delta) + expect(a).toBeCloseTo(b, places) ?''' +# __pragma__('nokwargs') def jest_test(test): diff --git a/test/metrics/test_egrid.py b/test/metrics/test_egrid.py index faefea4..3c7c7d7 100644 --- a/test/metrics/test_egrid.py +++ b/test/metrics/test_egrid.py @@ -29,7 +29,7 @@ async def test_egrid_intensity_cincinnati_2022(): "requested_coords": coords, "egrid_region": "RFCW", } - expectAlmostEqual(kg_per_kwh, expected_kg_per_kwh, delta=0.01) + expectAlmostEqual(kg_per_kwh, expected_kg_per_kwh, places=2) for key in expected_metadata.keys(): expectEqual(metadata[key], expected_metadata[key]) @@ -51,7 +51,7 @@ async def test_egrid_intensity_eagle_point_2023(): "requested_coords": coords, "egrid_region": "NWPP", } - expectAlmostEqual(kg_per_kwh, expected_kg_per_kwh, delta=0.01) + expectAlmostEqual(kg_per_kwh, expected_kg_per_kwh, places=2) for key in expected_metadata.keys(): expectEqual(metadata[key], expected_metadata[key]) diff --git a/test/metrics/test_footprint_calculations.py b/test/metrics/test_footprint_calculations.py index 1d62b6c..e36594e 100644 --- a/test/metrics/test_footprint_calculations.py +++ b/test/metrics/test_footprint_calculations.py @@ -26,7 +26,7 @@ async def test_car_footprint(): expected_footprint = {'kwh': 0.899, 'kg_co2': 0.291} for key in expected_footprint.keys(): - expectAlmostEqual(footprint[key], expected_footprint[key], delta=0.001) + expectAlmostEqual(footprint[key], expected_footprint[key], places=3) # with 2 passengers, the footprint should be halved fake_label_options['MODE'][0]['passengers'] = 2 @@ -35,7 +35,7 @@ async def test_car_footprint(): expected_footprint = {'kwh': 0.899 / 2, 'kg_co2': 0.291 / 2} for key in expected_footprint.keys(): - expectAlmostEqual(footprint[key], expected_footprint[key], delta=0.001) + expectAlmostEqual(footprint[key], expected_footprint[key], places=3) @jest_test @@ -60,7 +60,7 @@ async def test_ebike_footprint(): expected_footprint = {'kwh': 0.014, 'kg_co2': 0.006} for key in expected_footprint.keys(): - expectAlmostEqual(footprint[key], expected_footprint[key], delta=0.001) + expectAlmostEqual(footprint[key], expected_footprint[key], places=3) @jest_test @@ -88,7 +88,7 @@ async def test_custom_car_footprint(): 'kg_co2': (0.1 / 1000) * emcmfu.FUELS_KG_CO2_PER_MWH['gasoline'] } for key in expected_footprint.keys(): - expectAlmostEqual(footprint[key], expected_footprint[key], delta=0.01) + expectAlmostEqual(footprint[key], expected_footprint[key], places=2) @jest_test @@ -111,7 +111,7 @@ async def test_nyc_bus_footprint(): (footprint, metadata) = await emcmff.calc_footprint_for_trip(fake_trip, fake_label_options) - expected_footprint = {'kwh': 12.93, 'kg_co2': 2.80} + expected_footprint = {'kwh': 12.82, 'kg_co2': 2.78} expected_metadata = { "data_sources": ["ntd2022", "egrid2022"], "is_provisional": False, @@ -120,7 +120,7 @@ async def test_nyc_bus_footprint(): "ntd_modes": ["MB", "RB", "CB"], } for key in expected_footprint.keys(): - expectAlmostEqual(footprint[key], expected_footprint[key], delta=0.01) + expectAlmostEqual(footprint[key], expected_footprint[key], places=2) for key in expected_metadata.keys(): expectEqual(metadata[key], expected_metadata[key]) @@ -156,8 +156,8 @@ async def test_impact_of_ebike_replacing_car(): kwh_saved = replaced_mode_footprint['kwh'] - mode_footprint['kwh'] kg_co2_saved = replaced_mode_footprint['kg_co2'] - mode_footprint['kg_co2'] - expectAlmostEqual(kwh_saved, 0.885, delta=0.001) - expectAlmostEqual(kg_co2_saved, 0.285, delta=0.001) + expectAlmostEqual(kwh_saved, 0.885, places=3) + expectAlmostEqual(kg_co2_saved, 0.285, places=3) jest_describe("test_footprint_calculations") diff --git a/test/metrics/test_transit.js b/test/metrics/test_transit.js index 2d146cc..ba94143 100644 --- a/test/metrics/test_transit.js +++ b/test/metrics/test_transit.js @@ -21,43 +21,43 @@ describe('TestTransit', () => { it('test_bus_nyc', async () => { const [intensities, metadata] = await emcft.get_transit_intensities_for_uace(2022, NYC_UACE_CODE, BUS_MODES); - expect(intensities['overall']['wh_per_km']).toBeCloseTo(646.80, 2); + expect(intensities['overall']['wh_per_km']).toBeCloseTo(641.24, 2); expect(metadata['ntd_ids'].length).toEqual(22); }); it('test_bus_chicago', async () => { const [intensities, metadata] = await emcft.get_transit_intensities_for_uace(2022, CHICAGO_UACE_CODE, BUS_MODES); - expect(intensities['overall']['wh_per_km']).toBeCloseTo(1048.12, 2); + expect(intensities['overall']['wh_per_km']).toBeCloseTo(1039.10, 2); expect(metadata['ntd_ids'].length).toEqual(2); }); it('test_bus_nationwide', async () => { const [intensities, metadata] = await emcft.get_transit_intensities_for_uace(2022, null, BUS_MODES); - expect(intensities['overall']['wh_per_km']).toBeCloseTo(811.85, 2); + expect(intensities['overall']['wh_per_km']).toBeCloseTo(804.91, 2); expect(metadata['ntd_ids'].length).toEqual(410); }); it('test_train_nyc', async () => { const [intensities, metadata] = await emcft.get_transit_intensities_for_uace(2022, NYC_UACE_CODE, TRAIN_MODES); - expect(intensities['overall']['wh_per_km']).toBeCloseTo(24.79, 2); + expect(intensities['overall']['wh_per_km']).toBeCloseTo(24.75, 2); expect(metadata['ntd_ids'].length).toEqual(6); }); it('test_train_chicago', async () => { const [intensities, metadata] = await emcft.get_transit_intensities_for_uace(2022, CHICAGO_UACE_CODE, TRAIN_MODES); - expect(intensities['overall']['wh_per_km']).toBeCloseTo(159.04, 2); + expect(intensities['overall']['wh_per_km']).toBeCloseTo(158.14, 2); expect(metadata['ntd_ids'].length).toEqual(3); }); it('test_train_nationwide', async () => { const [intensities, metadata] = await emcft.get_transit_intensities_for_uace(2022, null, TRAIN_MODES); - expect(intensities['overall']['wh_per_km']).toBeCloseTo(68.06, 2); + expect(intensities['overall']['wh_per_km']).toBeCloseTo(67.87, 2); expect(metadata['ntd_ids'].length).toEqual(49); }); it('test_all_modes_nationwide', async () => { const [intensities, metadata] = await emcft.get_transit_intensities_for_uace(2022, null, null); - expect(intensities['overall']['wh_per_km']).toBeCloseTo(486.96, 2); + expect(intensities['overall']['wh_per_km']).toBeCloseTo(483.04, 2); expect(metadata['ntd_ids'].length).toEqual(517); }); }); diff --git a/test/metrics/test_transit.py b/test/metrics/test_transit.py index bc9e2bc..5bcd95d 100644 --- a/test/metrics/test_transit.py +++ b/test/metrics/test_transit.py @@ -19,38 +19,38 @@ async def test_get_uace_by_coords(self): async def test_bus_nyc(self): (intensities, metadata) = await emcmft.get_transit_intensities_for_uace(2022, NYC_UACE_CODE, BUS_MODES) - self.assertAlmostEqual(intensities['overall']['wh_per_km'], 646.80, places=2) + self.assertAlmostEqual(intensities['overall']['wh_per_km'], 641.24, places=2) self.assertEqual(len(metadata['ntd_ids']), 22) async def test_bus_chicago(self): (intensities, metadata) = await emcmft.get_transit_intensities_for_uace(2022, CHICAGO_UACE_CODE, BUS_MODES) - self.assertAlmostEqual(intensities['overall']['wh_per_km'], 1048.12, places=2) + self.assertAlmostEqual(intensities['overall']['wh_per_km'], 1039.10, places=2) self.assertEqual(len(metadata['ntd_ids']), 2) async def test_bus_nationwide(self): (intensities, metadata) = await emcmft.get_transit_intensities_for_uace(2022, None, BUS_MODES) - self.assertAlmostEqual(intensities['overall']['wh_per_km'], 811.85, places=2) + self.assertAlmostEqual(intensities['overall']['wh_per_km'], 804.91, places=2) self.assertEqual(len(metadata['ntd_ids']), 410) async def test_train_nyc(self): (intensities, metadata) = await emcmft.get_transit_intensities_for_uace(2022, NYC_UACE_CODE, TRAIN_MODES) - self.assertAlmostEqual(intensities['overall']['wh_per_km'], 24.79, places=2) + self.assertAlmostEqual(intensities['overall']['wh_per_km'], 24.75, places=2) self.assertEqual(len(metadata['ntd_ids']), 6) async def test_train_chicago(self): (intensities, metadata) = await emcmft.get_transit_intensities_for_uace(2022, CHICAGO_UACE_CODE, TRAIN_MODES) - self.assertAlmostEqual(intensities['overall']['wh_per_km'], 159.04, places=2) + self.assertAlmostEqual(intensities['overall']['wh_per_km'], 158.14, places=2) # 3 passenger rail systems in Chicago - "the L", Metra, and South Shore Line self.assertEqual(len(metadata['ntd_ids']), 3) async def test_train_nationwide(self): (intensities, metadata) = await emcmft.get_transit_intensities_for_uace(2022, None, TRAIN_MODES) - self.assertAlmostEqual(intensities['overall']['wh_per_km'], 68.06, places=2) + self.assertAlmostEqual(intensities['overall']['wh_per_km'], 67.87, places=2) self.assertEqual(len(metadata['ntd_ids']), 49) async def test_all_modes_nationwide(self): (intensities, metadata) = await emcmft.get_transit_intensities_for_uace(2022, None, None) - self.assertAlmostEqual(intensities['overall']['wh_per_km'], 486.96, places=2) + self.assertAlmostEqual(intensities['overall']['wh_per_km'], 483.04, places=2) self.assertEqual(len(metadata['ntd_ids']), 517)