• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

blue-marble / gridpath / 17838580391

18 Sep 2025 06:56PM UTC coverage: 89.046% (+0.09%) from 88.959%
17838580391

push

github

web-flow
Maintenance upgrades (#1289)

Support Python 3.12 and 3.13, drop testing on Python 3.9 and 3.10.

Upgrade dependencies to latest versions.

Notes testing with coverage sees significant slowdown with Python 3.13.

55 of 65 new or added lines in 48 files covered. (84.62%)

2 existing lines in 2 files now uncovered.

27680 of 31085 relevant lines covered (89.05%)

2.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.11
/tests/test_examples.py
1
# Copyright 2016-2025 Blue Marble Analytics LLC.
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
6
#
7
#     http://www.apache.org/licenses/LICENSE-2.0
8
#
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
14

15
import ast
3✔
16
import csv
3✔
17
import logging
3✔
18
import multiprocessing
3✔
19
import os
3✔
20
import pandas as pd
3✔
21
import platform
3✔
22
import sqlite3
3✔
23
import unittest
3✔
24

25
from gridpath import run_end_to_end, run_scenario, validate_inputs
3✔
26
from db import create_database
3✔
27
from db.common_functions import connect_to_database
3✔
28
from db.utilities import port_csvs_to_db, scenario
3✔
29

30
# Change directory to 'gridpath' directory, as that's what run_scenario.py
31
# expects; the rest of the global variables are relative paths from there
32
os.chdir(os.path.join(os.path.dirname(__file__), "..", "gridpath"))
3✔
33
EXAMPLES_DIRECTORY = os.path.join("..", "examples")
3✔
34
DB_NAME = "unittest_examples"
3✔
35
DB_PATH = f"../db/{DB_NAME}.db"
3✔
36
DB_SCHEMA = f"../db/db_schema.sql"
3✔
37
DATA_DIRECTORY = "../db/data"
3✔
38
CSV_PATH = "../db//csvs_test_examples"
3✔
39
SCENARIOS_CSV = os.path.join(CSV_PATH, "scenarios.csv")
3✔
40
TEST_SCENARIOS_CSV = "../tests/test_data/test_scenario_objective_function_values.csv"
3✔
41

42
# Platform check
43
LINUX = True if platform.system() == "Linux" else False
3✔
44
MACOS = True if platform.system() == "Darwin" else False
3✔
45
WINDOWS = True if platform.system() == "Windows" else False
3✔
46

47
# Python version
48
PYTHON_VERSION = platform.python_version()
3✔
49

50

51
class TestExamples(unittest.TestCase):
3✔
52
    """ """
53

54
    df = pd.read_csv(TEST_SCENARIOS_CSV, delimiter=",")
3✔
55
    df.set_index("test_scenario", inplace=True)
3✔
56

57
    def assertDictAlmostEqual(self, d1, d2, msg=None, places=7):
3✔
58
        # check if both inputs are dicts
59
        self.assertIsInstance(d1, dict, "First argument is not a dictionary")
3✔
60
        self.assertIsInstance(d2, dict, "Second argument is not a dictionary")
3✔
61

62
        # check if both inputs have the same keys
63
        self.assertEqual(d1.keys(), d2.keys())
3✔
64

65
        # check each key
66
        for key, value in d1.items():
3✔
67
            if isinstance(value, dict):
3✔
68
                self.assertDictAlmostEqual(d1[key], d2[key], places=places, msg=msg)
3✔
69
            else:
70
                self.assertAlmostEqual(d1[key], d2[key], places=places, msg=msg)
3✔
71

72
    def check_validation(self, test):
3✔
73
        """
74
        Check that validate inputs runs without errors, and that there
75
        are no validation issues recorded in the status_validation table
76
        :return:
77
        """
78

79
        # Check that test validation runs without errors
80
        validate_inputs.main(["--database", DB_PATH, "--scenario", test, "--quiet"])
3✔
81

82
        # Check that no validation issues are recorded in the db for the test
83
        expected_validations = []
3✔
84

85
        conn = connect_to_database(
3✔
86
            db_path=DB_PATH, detect_types=sqlite3.PARSE_DECLTYPES
87
        )
88
        c = conn.cursor()
3✔
89
        validations = c.execute(
3✔
90
            """
91
            SELECT scenario_name FROM status_validation
92
            INNER JOIN
93
            (SELECT scenario_id, scenario_name FROM scenarios)
94
            USING (scenario_id)
95
            WHERE scenario_name = '{}'
96
            """.format(
97
                test
98
            )
99
        )
100
        actual_validations = validations.fetchall()
3✔
101
        conn.close()
3✔
102

103
        self.assertListEqual(expected_validations, actual_validations)
3✔
104

105
    def run_and_check_objective(
3✔
106
        self, test, expected_objective, solver=None, parallel=1
107
    ):
108
        """
109

110
        :param test: str, name of the test example
111
        :param expected_objective: float or dict, expected objective
112
        :param parallel: int, set to a number > 1 to test
113
            parallelization functionality
114
        :return:
115
        """
116
        args_to_pass = [
3✔
117
            "--database",
118
            DB_PATH,
119
            "--scenario",
120
            test,
121
            "--scenario_location",
122
            EXAMPLES_DIRECTORY,
123
            # "--log",
124
            # "--write_solver_files_to_logs_dir",
125
            # "--keepfiles",
126
            # "--symbolic",
127
            "--n_parallel_get_inputs",
128
            str(parallel),
129
            "--n_parallel_solve",
130
            str(parallel),
131
            "--quiet",
132
            "--mute_solver_output",
133
            "--testing",
134
        ]
135
        if solver is not None:
3✔
136
            args_to_pass.append("--solver")
×
137
            args_to_pass.append(solver)
×
138

139
        actual_objective = run_end_to_end.main(args_to_pass)
3✔
140

141
        # Check if we have a multiprocessing manager
142
        # If so, convert the manager proxy dictionary to a simple dictionary
143
        # to avoid errors
144
        # Done via copies to avoid broken pipe error
145
        if hasattr(multiprocessing, "managers"):
3✔
146
            if isinstance(actual_objective, multiprocessing.managers.DictProxy):
3✔
147
                # Make a dictionary from a copy of the objective
148
                actual_objective_copy = dict(actual_objective.copy())
×
149
                for subproblem in actual_objective.keys():
×
150
                    # If we have stages, make a dictionary form a copy of the
151
                    # stage dictionary for each subproblem
152
                    if isinstance(
×
153
                        actual_objective[subproblem], multiprocessing.managers.DictProxy
154
                    ):
155
                        stage_dict_copy = dict(actual_objective_copy[subproblem].copy())
×
156
                        # Reset the stage dictionary to the new simple
157
                        # dictionary object
158
                        actual_objective_copy[subproblem] = stage_dict_copy
×
159
                # Reset the objective to the new dictionary object
160
                actual_objective = actual_objective_copy
×
161

162
        # Uncomment this to save new objective function values
163
        df = pd.read_csv(TEST_SCENARIOS_CSV, delimiter=",")
3✔
164
        df.set_index("test_scenario", inplace=True)
3✔
165
        # Set dtype to 'object' so that we can have floats and dictionaries
166
        # in the column
167
        df["actual_objective"] = df["actual_objective"].astype("object")
3✔
168
        df.at[test, "actual_objective"] = actual_objective
3✔
169
        df.to_csv(TEST_SCENARIOS_CSV, index=True)
3✔
170

171
        # Multi-subproblem and/or multi-stage scenarios return dict
172
        if isinstance(expected_objective, dict):
3✔
173
            self.assertDictAlmostEqual(expected_objective, actual_objective, places=1)
3✔
174
        # Otherwise, objective is a single value
175
        else:
176
            self.assertAlmostEqual(expected_objective, actual_objective, places=1)
×
177

178
    @classmethod
3✔
179
    def setUpClass(cls):
3✔
180
        """
181
        Set up the testing database
182
        :return:
183
        """
184

185
        if os.path.exists(DB_PATH):
3✔
186
            os.remove(DB_PATH)
×
187

188
        create_database.main(
3✔
189
            [
190
                "--database",
191
                DB_PATH,
192
                "--db_schema",
193
                DB_SCHEMA,
194
                "--data_directory",
195
                DATA_DIRECTORY,
196
            ]
197
        )
198

199
        try:
3✔
200
            port_csvs_to_db.main(
3✔
201
                ["--database", DB_PATH, "--csv_location", CSV_PATH, "--quiet"]
202
            )
203
        except Exception as e:
×
204
            print(
×
205
                "Error encountered during population of testing database "
206
                "{}.db. Deleting database ...".format(DB_NAME)
207
            )
208
            logging.exception(e)
×
209
            os.remove(DB_PATH)
×
210

211
        try:
3✔
212
            scenario.main(
3✔
213
                ["--database", DB_PATH, "--csv_path", SCENARIOS_CSV, "--quiet"]
214
            )
215
        except Exception as e:
×
216
            print(
×
217
                "Error encountered during population of testing database "
218
                "{}.db. Deleting database ...".format(DB_NAME)
219
            )
220
            logging.exception(e)
×
221
            os.remove(DB_PATH)
×
222

223
    def validate_and_test_example_generic(
3✔
224
        self, scenario_name, solver=None, skip_validation=False
225
    ):
226
        # Use the expected objective column by default
227
        column_to_use = "expected_objective"
3✔
228
        if MACOS and not pd.isnull(
3✔
229
            self.df.loc[scenario_name]["expected_objective_darwin"]
230
        ):
231
            column_to_use = "expected_objective_darwin"
×
232
        if WINDOWS and not pd.isnull(
3✔
233
            self.df.loc[scenario_name]["expected_objective_windows"]
234
        ):
235
            column_to_use = "expected_objective_windows"
×
236

237
        # Evaluate the objective function as a literal (as it is in
238
        # dictionary format stored as string in the CSV)
239
        # This is now done for all scenarios, even if they have no iterations
240
        # or multiple subproblem/stages
241
        objective = ast.literal_eval(self.df.loc[scenario_name][column_to_use])
3✔
242

243
        # On Python <3.12, we have one example with a slightly different
244
        # objective function value; set it here
245
        # Remove this when we stop supporting Python <3.12
246
        if (
3✔
247
            PYTHON_VERSION < "3.12"
248
            and scenario_name == "test_new_solar_carbon_credits_w_sell"
249
        ):
250
            objective = ast.literal_eval("{('', '', '', 1): {1: 978964234435709.4}}")
1✔
251

252
        if not skip_validation:
3✔
253
            self.check_validation(scenario_name)
3✔
254
        self.run_and_check_objective(
3✔
255
            test=scenario_name, solver=solver, expected_objective=objective
256
        )
257

258
    def test_example_test(self):
3✔
259
        """
260
        Check validation and objective function value of "test" example
261
        :return:
262
        """
263
        scenario_name = "test"
3✔
264
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
265

266
    def test_example_test_no_overgen_allowed(self):
3✔
267
        """
268
        Check validation and objective function value of
269
        "test_no_overgen_allowed" example
270
        :return:
271
        """
272

273
        scenario_name = "test_no_overgen_allowed"
3✔
274
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
275

276
    def test_example_test_new_build_storage(self):
3✔
277
        """
278
        Check validation and objective function value of
279
        "test_new_build_storage" example
280
        :return:
281
        """
282

283
        scenario_name = "test_new_build_storage"
3✔
284
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
285

286
    def test_example_test_new_binary_build_storage(self):
3✔
287
        """
288
        Check validation and objective function value of
289
        "test_new_binary_build_storage" example
290
        :return:
291
        """
292
        scenario_name = "test_new_binary_build_storage"
3✔
293
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
294

295
    def test_example_test_new_build_storage_cumulative_min_max(self):
3✔
296
        """
297
        Check validation and objective function value of
298
        "test_new_build_storage_cumulative_min_max" example
299
        :return:
300
        """
301
        scenario_name = "test_new_build_storage_cumulative_min_max"
3✔
302
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
303

304
    def test_example_test_no_reserves(self):
3✔
305
        """
306
        Check validation and objective function value of
307
        "test_no_reserves" example
308
        :return:
309
        """
310
        scenario_name = "test_no_reserves"
3✔
311
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
312

313
    def test_example_test_w_hydro(self):
3✔
314
        """
315
        Check validation and objective function value of "test_w_hydro" example
316
        :return:
317
        """
318
        scenario_name = "test_w_hydro"
3✔
319
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
320

321
    def test_example_test_w_storage(self):
3✔
322
        """
323
        Check validation and objective function value of "test_w_storage" example
324
        :return:
325
        """
326
        scenario_name = "test_w_storage"
3✔
327
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
328

329
    def test_example_2horizons(self):
3✔
330
        """
331
        Check validation and objective function value of "2horizons" example
332
        :return:
333
        """
334
        scenario_name = "2horizons"
3✔
335
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
336

337
    def test_example_2horizons_w_hydro(self):
3✔
338
        """
339
        Check validation and objective function value of
340
        "2horizons_w_hydro" example
341
        :return:
342
        """
343
        scenario_name = "2horizons_w_hydro"
3✔
344
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
345

346
    def test_example_2horizons_w_hydro_and_nuclear_binary_availability(self):
3✔
347
        """
348
        Check validation and objective function value of
349
        "2horizons_w_hydro_and_nuclear_binary_availability" example
350

351
        NOTE: the objective function for this example is lower than that for
352
        the '2horizons_w_hydro' example because of the unrealistically high
353
        relative heat rate of the 'Nuclear' project relative to the gas
354
        projects; allowing binary availability for a must-run project
355
        actually allows lower-cost power when the nuclear plant is
356
        unavailable. We should probably re-think this example as part of a
357
        future more general revamp of the examples.
358

359
        :return:
360
        """
361
        scenario_name = "2horizons_w_hydro_and_nuclear_binary_availability"
3✔
362
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
363

364
    def test_example_2horizons_w_hydro_w_balancing_types(self):
3✔
365
        """
366
        Check validation and objective function value of
367
        "2horizons_w_hydro_w_balancing_types" example. The objective
368
        function of this example should be lower than that of the
369
        '2horizons_w_hydro' example, as the average hydro budget is the
370
        same across all timepoints, but the hydro balancing horizon is now
371
        longer.
372
        :return:
373
        """
374
        scenario_name = "2horizons_w_hydro_w_balancing_types"
3✔
375
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
376

377
    def test_example_2periods(self):
3✔
378
        """
379
        Check validation and objective function value of "2periods" example
380
        :return:
381
        """
382
        scenario_name = "2periods"
3✔
383
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
384

385
    def test_example_2periods_new_build(self):
3✔
386
        """
387
        Check validation and objective function value of "2periods_new_build" example
388
        """
389
        scenario_name = "2periods_new_build"
3✔
390
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
391

392
    def test_example_2periods_new_build_2zones(self):
3✔
393
        """
394
        Check validation and objective function value of
395
        "2periods_new_build_2zones" example
396
        :return:
397
        """
398
        scenario_name = "2periods_new_build_2zones"
3✔
399
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
400

401
    def test_example_2periods_new_build_2zones_new_build_transmission(self):
3✔
402
        """
403
        Check validation and objective function value of
404
        "2periods_new_build_2zones_new_build_transmission" example
405
        :return:
406
        """
407
        scenario_name = "2periods_new_build_2zones_new_build_transmission"
3✔
408
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
409

410
    def test_example_2periods_new_build_2zones_singleBA(self):
3✔
411
        """
412
        Check validation and objective function value of
413
        "2periods_new_build_2zones_singleBA"
414
        example
415
        :return:
416
        """
417
        scenario_name = "2periods_new_build_2zones_singleBA"
3✔
418
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
419

420
    def test_example_2periods_new_build_2zones_transmission(self):
3✔
421
        """
422
        Check validation and objective function value of
423
        "2periods_new_build_2zones_transmission" example
424
        :return:
425
        """
426
        scenario_name = "2periods_new_build_2zones_transmission"
3✔
427
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
428

429
    def test_example_2periods_new_build_2zones_transmission_w_losses(self):
3✔
430
        """
431
        Check validation and objective function value of
432
        "2periods_new_build_2zones_transmission_w_losses" example
433
        :return:
434
        """
435
        scenario_name = "2periods_new_build_2zones_transmission_w_losses"
3✔
436
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
437

438
    def test_example_2periods_new_build_2zones_transmission_w_losses_opp_dir(self):
3✔
439
        """
440
        Check validation and objective function value of
441
        "2periods_new_build_2zones_transmission_w_losses_opp_dir" example
442

443
        Note: this should be the same as the objective function for
444
        2periods_new_build_2zones_transmission_w_losses
445
        :return:
446
        """
447
        scenario_name = "2periods_new_build_2zones_transmission_w_losses_opp_dir"
3✔
448
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
449

450
    def test_example_2periods_new_build_rps(self):
3✔
451
        """
452
        Check validation and objective function value of
453
        "2periods_new_build_rps" example
454
        :return:
455
        """
456
        scenario_name = "2periods_new_build_rps"
3✔
457
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
458

459
    def test_example_2periods_new_build_rps_percent_target(self):
3✔
460
        """
461
        Check objective function value of
462
        "2periods_new_build_rps_percent_target" example
463
        This example should have the same objective function as
464
        test_example_2periods_new_build_rps, as its target is the same,
465
        but specified as percentage of load.
466
        :return:
467
        """
468
        scenario_name = "2periods_new_build_rps_percent_target"
3✔
469
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
470

471
    def test_example_2periods_new_build_cumulative_min_max(self):
3✔
472
        """
473
        Check validation and objective function value of
474
        "2periods_new_build_cumulative_min_max" example
475
        :return:
476
        """
477
        scenario_name = "2periods_new_build_cumulative_min_max"
3✔
478
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
479

480
    def test_example_single_stage_prod_cost(self):
3✔
481
        """
482
        Check validation and objective function values of
483
        "single_stage_prod_cost" example
484
        :return:
485
        """
486
        scenario_name = "single_stage_prod_cost"
3✔
487
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
488

489
    def test_example_single_stage_prod_cost_linked_subproblems(self):
3✔
490
        """
491
        Check objective function values of
492
        "single_stage_prod_cost_linked_subproblems" example
493
        :return:
494
        """
495
        scenario_name = "single_stage_prod_cost_linked_subproblems"
3✔
496
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
497

498
    def test_example_single_stage_prod_cost_linked_subproblems_w_hydro(self):
3✔
499
        """
500
        Check objective function values of
501
        "single_stage_prod_cost_linked_subproblems" example
502
        :return:
503
        """
504
        scenario_name = "single_stage_prod_cost_linked_subproblems_w_hydro"
3✔
505
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
506

507
    def test_example_multi_stage_prod_cost(self):
3✔
508
        """
509
        Check validation and objective function values of
510
        "multi_stage_prod_cost" example
511
        :return:
512
        """
513
        scenario_name = "multi_stage_prod_cost"
3✔
514
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
515

516
    def test_example_single_stage_prod_cost_cycle_select(self):
3✔
517
        """
518
        Check validation and objective function values of
519
        "single_stage_prod_cost_cycle_select" example. This example is the same as
520
        single_stage_prod_cost but the Coal and Gas_CCGT plants have mutually
521
        exclusive commitment in this example.
522
        """
523
        scenario_name = "single_stage_prod_cost_cycle_select"
3✔
524
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
525

526
    def test_example_multi_stage_prod_cost_parallel(self):
3✔
527
        """
528
        Check "multi_stage_prod_cost" example running subproblems in parallel
529
        (getting inputs and optimization)
530
        :return:
531
        """
532
        run_end_to_end.main(
3✔
533
            [
534
                "--database",
535
                DB_PATH,
536
                "--scenario",
537
                "multi_stage_prod_cost",
538
                "--scenario_location",
539
                EXAMPLES_DIRECTORY,
540
                # "--log",
541
                # "--write_solver_files_to_logs_dir",
542
                # "--keepfiles",
543
                # "--symbolic",
544
                "--n_parallel_get_inputs",
545
                "3",
546
                "--n_parallel_solve",
547
                "3",
548
                "--quiet",
549
                "--mute_solver_output",
550
                "--testing",
551
            ]
552
        )
553

554
    def test_example_multi_stage_prod_cost_w_hydro(self):
3✔
555
        """
556
        Check validation and objective function values of
557
        "multi_stage_prod_cost_w_hydro"
558
        example
559
        :return:
560
        """
561
        scenario_name = "multi_stage_prod_cost_w_hydro"
3✔
562
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
563

564
    def test_example_multi_stage_prod_cost_linked_subproblems(self):
3✔
565
        """
566
        Check validation and objective function values of
567
        "multi_stage_prod_cost_linked_subproblems" example
568
        :return:
569
        """
570
        scenario_name = "multi_stage_prod_cost_linked_subproblems"
3✔
571
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
572

573
    def test_example_2periods_gen_lin_econ_retirement(self):
3✔
574
        """
575
        Check validation and objective function value of
576
        "2periods_gen_lin_econ_retirement"
577
        example
578
        :return:
579
        """
580
        scenario_name = "2periods_gen_lin_econ_retirement"
3✔
581
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
582

583
    def test_example_2periods_gen_bin_econ_retirement(self):
3✔
584
        """
585
        Check validation and objective function value of
586
        "2periods_gen_bin_econ_retirement"
587
        example
588
        :return:
589
        """
590
        scenario_name = "2periods_gen_bin_econ_retirement"
3✔
591
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
592

593
    def test_example_variable_gen_reserves(self):
3✔
594
        """
595
        Check validation and objective function value of
596
        "variable_gen_reserves"
597
        example; this example requires a non-linear solver
598
        :return:
599
        """
600
        scenario_name = "test_variable_gen_reserves"
3✔
601
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
602

603
    def test_example_2periods_new_build_rps_variable_reserves(self):
3✔
604
        """
605
        Check validation and objective function value of
606
        "2periods_new_build_rps_variable_reserves" example
607
        :return:
608
        """
609
        scenario_name = "2periods_new_build_rps_variable_reserves"
3✔
610
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
611

612
    def test_example_2periods_new_build_rps_variable_reserves_subhourly_adj(self):
3✔
613
        """
614
        Check validation and objective function value of
615
        "2periods_new_build_rps_variable_reserves_subhourly_adj" example
616
        :return:
617
        """
618
        scenario_name = "2periods_new_build_rps_variable_reserves_subhourly_adj"
3✔
619
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
620

621
    def test_example_test_ramp_up_constraints(self):
3✔
622
        """
623
        Check validation and objective function value of
624
        "test_ramp_up_constraints" example
625
        :return:
626
        """
627
        scenario_name = "test_ramp_up_constraints"
3✔
628
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
629

630
    def test_example_test_ramp_up_and_down_constraints(self):
3✔
631
        """
632
        Check validation and objective function value of
633
        "test_ramp_up_and_down_constraints"
634
        example;
635
        :return:
636
        """
637
        scenario_name = "test_ramp_up_and_down_constraints"
3✔
638
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
639

640
    def test_example_2periods_new_build_rps_w_rps_ineligible_storage(self):
3✔
641
        """
642
        Check validation and objective function value of
643
        "2periods_new_build_rps_w_rps_ineligible_storage" example
644
        :return:
645
        """
646
        scenario_name = "2periods_new_build_rps_w_rps_ineligible_storage"
3✔
647
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
648

649
    def test_example_2periods_new_build_rps_w_rps_eligible_storage(self):
3✔
650
        """
651
        Check validation and objective function value of
652
        "2periods_new_build_rps_w_rps_eligible_storage" example
653
        :return:
654
        """
655
        scenario_name = "2periods_new_build_rps_w_rps_eligible_storage"
3✔
656
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
657

658
    def test_example_test_new_solar(self):
3✔
659
        """
660
        Check validation and objective function value of
661
        "test_new_solar" example
662
        :return:
663
        """
664
        scenario_name = "test_new_solar"
3✔
665
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
666

667
    def test_example_test_new_binary_solar(self):
3✔
668
        """
669
        Check validation and objective function value of
670
        "test_new_binary_solar" example
671
        :return:
672
        """
673
        scenario_name = "test_new_binary_solar"
3✔
674
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
675

676
    def test_example_test_new_solar_carbon_cap(self):
3✔
677
        """
678
        Check validation and objective function value of
679
        "test_new_solar_carbon_cap" example
680
        :return:
681
        """
682
        scenario_name = "test_new_solar_carbon_cap"
3✔
683
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
684

685
    def test_example_test_new_solar_carbon_cap_2zones_tx(self):
3✔
686
        """
687
        Check validation and objective function value of
688
        "test_new_solar_carbon_cap_2zones_tx" example
689
        :return:
690
        """
691
        scenario_name = "test_new_solar_carbon_cap_2zones_tx"
3✔
692
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
693

694
    def test_example_test_new_solar_carbon_cap_2zones_dont_count_tx(self):
3✔
695
        """
696
        Check validation and objective function value of
697
        "test_new_solar_carbon_cap_2zones_dont_count_tx" example
698
        :return:
699
        """
700
        scenario_name = "test_new_solar_carbon_cap_2zones_dont_count_tx"
3✔
701
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
702

703
    def test_example_test_new_solar_carbon_tax(self):
3✔
704
        """
705
        Check validation and objective function value of
706
        "test_new_solar_carbon_tax" example
707
        :return:
708
        """
709
        scenario_name = "test_new_solar_carbon_tax"
3✔
710
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
711

712
    def test_example_2periods_new_build_simple_prm(self):
3✔
713
        """
714
        Check validation and objective function value of
715
        "2periods_new_build_simple_prm"
716
        example
717
        :return:
718
        """
719
        scenario_name = "2periods_new_build_simple_prm"
3✔
720
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
721

722
    def test_example_2periods_new_build_simple_prm_w_energy_only(self):
3✔
723
        """
724
        Check validation and objective function value of
725
        "2periods_new_build_simple_prm"
726
        example
727
        :return:
728
        """
729
        scenario_name = "2periods_new_build_simple_prm_w_energy_only"
3✔
730
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
731

732
    def test_example_2periods_new_build_simple_prm_w_energy_only_deliv_cap_limit(self):
3✔
733
        """
734
        Check validation and objective function value of
735
        "2periods_new_build_simple_prm"
736
        example
737
        :return:
738
        """
739
        scenario_name = "2periods_new_build_simple_prm_w_energy_only_deliv_cap_limit"
3✔
740
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
741

742
    def test_example_2periods_new_build_local_capacity(self):
3✔
743
        """
744
        Check validation and objective function value of
745
        "2periods_new_build_local_capacity"
746
        example
747
        :return:
748
        """
749
        scenario_name = "2periods_new_build_local_capacity"
3✔
750
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
751

752
    def test_example_test_tx_dcopf(self):
3✔
753
        """
754
        Check validation and objective function value of
755
        "test_tx_dcopf" example
756
        :return:
757
        """
758
        scenario_name = "test_tx_dcopf"
3✔
759
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
760

761
    def test_example_test_tx_simple(self):
3✔
762
        """
763
        Check validation and objective function value of
764
        "test_tx_simple" example
765
        :return:
766
        """
767
        scenario_name = "test_tx_simple"
3✔
768
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
769

770
    def test_example_test_tx_simple_tmp_emissions(self):
3✔
771
        """
772
        Check validation and objective function value of
773
        "test_tx_simple_tmp_emissions" example
774
        :return:
775
        """
776
        scenario_name = "test_tx_simple_tmp_emissions"
3✔
777
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
778

779
    def test_example_test_tx_simple_additive(self):
3✔
780
        """
781
        Check validation and objective function value of
782
        "test_tx_simple_additive" example
783
        :return:
784
        """
785
        scenario_name = "test_tx_simple_additive"
3✔
786
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
787

788
    def test_example_test_startup_shutdown_rates(self):
3✔
789
        """
790
        Check validation and objective function value of
791
        "test_startup_shutdown_rates"
792
        example
793
        :return:
794
        """
795
        scenario_name = "test_startup_shutdown_rates"
3✔
796
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
797

798
    def test_no_fuels(self):
3✔
799
        """
800
        Check validation and objective function value of "test_no_fuels"
801
        example
802
        :return:
803
        """
804
        scenario_name = "test_no_fuels"
3✔
805
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
806

807
    def test_variable_om_curves(self):
3✔
808
        """
809
        Check validation and objective function value of
810
        "test_variable_om_curves"
811
        example
812
        :return:
813
        """
814
        scenario_name = "test_variable_om_curves"
3✔
815
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
816

817
    def test_aux_cons(self):
3✔
818
        """
819
        Check validation and objective function value of
820
        "test_aux_cons" example
821

822
        Note: the objective function value is lower than that for the "test"
823
        example because the auxiliary consumption results in less
824
        overgeneration and therefore lower overgeneration penalty.
825
        """
826
        scenario_name = "test_aux_cons"
3✔
827
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
828

829
    def test_example_test_w_lf_down_percent_req(self):
3✔
830
        """
831
        Check validation and objective function value of
832
        "test_w_lf_down_percent_req" example
833
        :return:
834
        """
835
        scenario_name = "test_w_lf_down_percent_req"
3✔
836
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
837

838
    def test_example_2periods_new_build_capgroups(self):
3✔
839
        """
840
        Check validation and objective function value of
841
        "test_example_2periods_new_build_capgroups" example
842
        """
843
        scenario_name = "2periods_new_build_capgroups"
3✔
844
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
845

846
    def test_example_test_markets(self):
3✔
847
        """
848
        Check validation and objective function value of "test" example
849
        :return:
850
        """
851
        scenario_name = "test_markets"
3✔
852
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
853

854
    def test_example_2periods_new_build_horizon_energy_target(self):
3✔
855
        """
856
        Check validation and objective function value of
857
        "test_example_2periods_new_build_horizon_energy_target" example
858
        :return:
859
        """
860
        scenario_name = "2periods_new_build_horizon_energy_target"
3✔
861
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
862

863
    def test_example_2periods_new_build_horizon_energy_target_halfyear(self):
3✔
864
        """
865
        Check validation and objective function value of
866
        "2periods_new_build_horizon_energy_target_halfyear" example
867
        :return:
868
        """
869
        scenario_name = "2periods_new_build_horizon_energy_target_halfyear"
3✔
870
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
871

872
    def test_example_test_new_build_gen_var_stor_hyb(self):
3✔
873
        """
874
        Check validation and objective function value of
875
        "test_new_build_gen_var_stor_hyb" example
876
        :return:
877
        """
878
        scenario_name = "test_new_build_gen_var_stor_hyb"
3✔
879
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
880

881
    def test_example_test_carbon_tax_allowance(self):
3✔
882
        """
883
        Check validation and objective function value of
884
        "test_carbon_tax_allowance" example
885
        :return:
886
        """
887
        scenario_name = "test_carbon_tax_allowance"
3✔
888
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
889

890
    def test_example_test_min_max_build_trans(self):
3✔
891
        """
892
        Check validation and objective function value of
893
        "test_min_max_build_trans" example
894
        :return:
895
        """
896
        scenario_name = "test_min_max_build_trans"
3✔
897
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
898

899
    def test_example_2periods_new_build_2zones_transmission_Tx1halfavail(self):
3✔
900
        """
901
        Check validation and objective function value of
902
        "2periods_new_build_2zones_transmission_Tx1halfavail" example
903
        :return:
904
        """
905
        scenario_name = "2periods_new_build_2zones_transmission_Tx1halfavail"
3✔
906
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
907

908
    def test_example_2periods_new_build_2zones_transmission_Tx1halfavailmonthly(self):
3✔
909
        """
910
        Check validation and objective function value of
911
        "2periods_new_build_2zones_transmission_Tx1halfavail" example
912
        :return:
913
        """
914
        scenario_name = "2periods_new_build_2zones_transmission_Tx1halfavailmonthly"
3✔
915
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
916

917
    def test_example_test_cheap_fuel_blend(self):
3✔
918
        """
919
        Check validation and objective function value of "test_cheap_fuel_blend" example
920
        :return:
921
        """
922
        scenario_name = "test_cheap_fuel_blend"
3✔
923
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
924

925
    def test_example_test_new_solar_carbon_cap_2zones_tx_low_carbon_fuel_blend(self):
3✔
926
        """
927
        Check validation and objective function value of
928
        "test_new_solar_carbon_cap_2zones_tx_low_carbon_fuel_blend" example
929
        :return:
930
        """
931
        scenario_name = "test_new_solar_carbon_cap_2zones_tx_low_carbon_fuel_blend"
3✔
932
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
933

934
    def test_example_test_cheap_fuel_blend_w_limit(self):
3✔
935
        """
936
        Check validation and objective function value of
937
        "test_cheap_fuel_blend_w_limit" example
938
        :return:
939
        """
940
        scenario_name = "test_cheap_fuel_blend_w_limit"
3✔
941
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
942

943
    def test_example_test_new_solar_fuel_burn_limit(self):
3✔
944
        """
945
        Check validation and objective function value of
946
        "test_new_solar_fuel_burn_limit" example. Inputs set up so that this should
947
        be the same as the "test_new_solar_carbon_cap" example.
948
        :return:
949
        """
950
        scenario_name = "test_new_solar_fuel_burn_limit"
3✔
951
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
952

953
    def test_example_test_new_solar_fuel_burn_limit_relative(self):
3✔
954
        """
955
        Check validation and objective function value of
956
        "test_new_solar_fuel_burn_limit_relative" example. Inputs set up so that this
957
        should be the same as the "test_new_solar_fuel_burn_limit" example.
958
        :return:
959
        """
960
        scenario_name = "test_new_solar_fuel_burn_limit_relative"
3✔
961
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
962

963
    def test_test_w_solver_options(self):
3✔
964
        """
965
        Check validation and objective function value of "test_w_solver_options" example
966
        :return:
967
        """
968
        scenario_name = "test_w_solver_options"
3✔
969
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
970

971
    def test_example_test_carbon_tax_allowance_with_different_fuel_groups(self):
3✔
972
        """
973
        Check validation and objective function value of
974
        "test_carbon_tax_allowance_with_different_fuel_groups" example
975
        :return:
976
        """
977
        scenario_name = "test_carbon_tax_allowance_with_different_fuel_groups"
3✔
978
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
979

980
    def test_performance_standard(self):
3✔
981
        """
982
        Check validation and objective function value of "test_performance_standard" example
983
        :return:
984
        """
985
        scenario_name = "test_performance_standard"
3✔
986
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
987

988
    def test_tx_flow(self):
3✔
989
        """
990
        Check validation and objective function value of
991
        "test_tx_flow" example
992
        :return:
993
        """
994
        scenario_name = "test_tx_flow"
3✔
995
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
996

997
    def test_example_test_new_solar_reserve_prj_contribution(self):
3✔
998
        """
999
        Check validation and objective function value of
1000
        "test_reserve_prj_contribution" example.
1001
        This example is based on "test_new_solar" with the only difference, the LF UP
1002
        requirement ID
1003
        :return:
1004
        """
1005
        scenario_name = "test_new_solar_reserve_prj_contribution"
3✔
1006
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1007

1008
    def test_test_new_solar_carbon_cap_2zones_tx_hydrogen_prod(self):
3✔
1009
        """
1010
        Check validation and objective function value of
1011
        "test_reserve_prj_contribution" example.
1012
        This example is based on "test_new_solar" with the only difference, the LF UP
1013
        requirement ID
1014
        :return:
1015
        """
1016
        scenario_name = "test_new_solar_carbon_cap_2zones_tx_hydrogen_prod"
3✔
1017
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1018

1019
    def test_test_new_solar_carbon_cap_2zones_tx_hydrogen_prod_new(self):
3✔
1020
        """
1021
        Check validation and objective function value of
1022
        "test_reserve_prj_contribution" example.
1023
        This example is based on "test_new_solar" with the only difference, the LF UP
1024
        requirement ID
1025
        :return:
1026
        """
1027
        scenario_name = "test_new_solar_carbon_cap_2zones_tx_hydrogen_prod_new"
3✔
1028
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1029

1030
    def test_example_test_new_solar_carbon_cap_dac(self):
3✔
1031
        """
1032
        Check validation and objective function value of
1033
        "test_new_solar_carbon_cap_dac" example.
1034

1035
        Note that the same version of Cbc (v2.10.5) produces a slightly different
1036
        objective function for this problem on Windows than on Mac.
1037
        :return:
1038
        """
1039
        scenario_name = "test_new_solar_carbon_cap_dac"
3✔
1040
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1041

1042
    def test_example_test_cap_factor_limits(self):
3✔
1043
        """
1044
        Check validation and objective function value of "test" example
1045
        :return:
1046
        """
1047
        scenario_name = "test_cap_factor_limits"
3✔
1048
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1049

1050
    def test_example_multi_stage_prod_cost_w_markets(self):
3✔
1051
        """
1052
        Check validation and objective function values of
1053
        "multi_stage_prod_cost_w_markets" example
1054
        :return:
1055
        """
1056
        scenario_name = "multi_stage_prod_cost_w_markets"
3✔
1057
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1058

1059
    def test_example_test_supplemental_firing(self):
3✔
1060
        """
1061
        Check validation and objective function value of "test_supplemental_firing" example
1062
        :return:
1063
        """
1064
        scenario_name = "test_supplemental_firing"
3✔
1065
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1066

1067
    def test_example_test_tx_capacity_groups(self):
3✔
1068
        """
1069
        Check validation and objective function value of
1070
        "test_tx_capacity_groups" example
1071
        :return:
1072
        """
1073
        scenario_name = "test_tx_capacity_groups"
3✔
1074
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1075

1076
    def test_example_2periods_new_build_fin_lifetime(self):
3✔
1077
        """
1078
        Check validation and objective function value of
1079
        "2periods_new_build_fin_lifetime" example. Same as "2periods_new_build" but
1080
        with shorter financial lifetimes and some fixed costs. Cost is lower because
1081
        the same payment is made fewer times.
1082
        """
1083
        scenario_name = "2periods_new_build_fin_lifetime"
3✔
1084
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1085

1086
    def test_example_2periods_new_build_cumulative_and_vintage_min_max(self):
3✔
1087
        """
1088
        Check validation and objective function value of
1089
        "2periods_new_build_cumulative_and_vintage_min_max" example. It is the same
1090
        as 2periods_new_build_cumulative_and_min_max but with a max in 2020 for the
1091
        CCGT to force early build and a min on the CT in 2030 to force more build.
1092

1093
        :return:
1094
        """
1095
        scenario_name = "2periods_new_build_cumulative_and_vintage_min_max"
3✔
1096
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1097

1098
    def test_example_test_w_storage_w_soc_penalty(self):
3✔
1099
        """
1100
        Check validation and objective function value of "test_w_storage_w_soc_penalty"
1101
        example
1102
        :return:
1103
        """
1104
        scenario_name = "test_w_storage_w_soc_penalty"
3✔
1105
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1106

1107
    def test_example_test_w_storage_w_soc_last_tmp_penalty(self):
3✔
1108
        """
1109
        Check validation and objective function value of "test_w_storage_w_soc_penalty"
1110
        example
1111
        :return:
1112
        """
1113
        scenario_name = "test_w_storage_w_soc_last_tmp_penalty"
3✔
1114
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1115

1116
    def test_example_test_new_solar_itc(self):
3✔
1117
        """
1118
        Check validation and objective function value of
1119
        "test_new_solar_itc" example
1120
        :return:
1121
        """
1122
        scenario_name = "test_new_solar_itc"
3✔
1123
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1124

1125
    def test_example_test_new_build_storage_itc(self):
3✔
1126
        """
1127
        Check validation and objective function value of
1128
        "test_new_build_storage" example
1129
        :return:
1130
        """
1131
        scenario_name = "test_new_build_storage_itc"
3✔
1132
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1133

1134
    def test_example_2periods_new_build_simple_prm_2loadzones(self):
3✔
1135
        """
1136
        Check validation and objective function value of
1137
        "2periods_new_build_simple_prm_2loadzones"
1138
        example
1139
        :return:
1140
        """
1141
        scenario_name = "2periods_new_build_simple_prm_2loadzones"
3✔
1142
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1143

1144
    def test_example_2periods_new_build_simple_prm_2loadzones_newtx_w_transfers(self):
3✔
1145
        """
1146
        Check validation and objective function value of
1147
        "2periods_new_build_simple_prm_w_transfers"
1148
        example
1149
        :return:
1150
        """
1151
        scenario_name = "2periods_new_build_simple_prm_2loadzones_newtx_w_transfers"
3✔
1152
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1153

1154
    def test_example_2periods_new_build_simple_prm_2loadzones_newtx_w_transfers_w_costs(
3✔
1155
        self,
1156
    ):
1157
        """
1158
        Check validation and objective function value of
1159
        "2periods_new_build_simple_prm_2loadzones_newtx_w_transfers_w_costs"
1160
        example
1161
        :return:
1162
        """
1163
        scenario_name = (
3✔
1164
            "2periods_new_build_simple_prm_2loadzones_newtx_w_transfers_w_costs"
1165
        )
1166
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1167

1168
    def test_example_test_w_flex_load(self):
3✔
1169
        """
1170
        Check validation and objective function value of "test_w_storage" example
1171
        :return:
1172
        """
1173
        scenario_name = "test_w_flex_load"
3✔
1174
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1175

1176
    def test_example_test_new_solar_w_relative_capacity_instead_of_potential(self):
3✔
1177
        """
1178
        Check validation and objective function value of
1179
        "test_new_solar" example
1180
        :return:
1181
        """
1182
        scenario_name = "test_new_solar_w_relative_capacity_instead_of_potential"
3✔
1183
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1184

1185
    def test_example_2periods_new_build_2zones_transmission_w_hurdle_rates(self):
3✔
1186
        """
1187
        Check validation and objective function value of
1188
        "2periods_new_build_2zones_transmission_w_hurdle_rates" example
1189
        :return:
1190
        """
1191
        scenario_name = "2periods_new_build_2zones_transmission_w_hurdle_rates"
3✔
1192
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1193

1194
    def test_example_2periods_new_build_2zones_transmission_w_hurdle_rates_by_timepoint(
3✔
1195
        self,
1196
    ):
1197
        """
1198
        Check validation and objective function value of
1199
        "2periods_new_build_2zones_transmission_w_hurdle_rates_by_timepoint" example
1200
        :return:
1201
        """
1202
        scenario_name = (
3✔
1203
            "2periods_new_build_2zones_transmission_w_hurdle_rates_by_timepoint"
1204
        )
1205
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1206

1207
    def test_example_2periods_new_build_2zones_transmission_w_hurdle_rates_by_timepoint_and_period(
3✔
1208
        self,
1209
    ):
1210
        """
1211
        Check validation and objective function value of
1212
        "2periods_new_build_2zones_transmission_w_hurdle_rates_by_timepoint_and_period" example
1213
        :return:
1214
        """
1215
        scenario_name = "2periods_new_build_2zones_transmission_w_hurdle_rates_by_timepoint_and_period"
3✔
1216
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1217

1218
    def test_example_2periods_new_build_simple_prm_2loadzones_newtx_w_transfers_w_subsidies(
3✔
1219
        self,
1220
    ):
1221
        """
1222
        Check validation and objective function value of
1223
        "test_new_solar" example
1224
        :return:
1225
        """
1226
        scenario_name = (
3✔
1227
            "2periods_new_build_simple_prm_2loadzones_newtx_w_transfers_w_subsidies"
1228
        )
1229
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1230

1231
    def test_example_test_new_build_storage_itc_single_superperiod(self):
3✔
1232
        """
1233
        Check validation and objective function value of
1234
        "test_new_build_storage_itc_single_superperiodself" example
1235
        :return:
1236
        """
1237
        scenario_name = "test_new_build_storage_itc_single_superperiod"
3✔
1238
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1239

1240
    def test_incomplete_only(self):
3✔
1241
        """
1242
        Check that the "incomplete only" functionality works with no errors.
1243
        :return:
1244
        """
1245
        actual_objective = run_scenario.main(
3✔
1246
            [
1247
                "--scenario",
1248
                "test",
1249
                "--scenario_location",
1250
                EXAMPLES_DIRECTORY,
1251
                "--quiet",
1252
                "--mute_solver_output",
1253
                "--incomplete_only",
1254
            ]
1255
        )
1256

1257
    def test_example_test_w_storage_starting_soc(self):
3✔
1258
        """
1259
        Check validation and objective function value of
1260
        "test_w_storage_starting_soc" example
1261
        :return:
1262
        """
1263
        scenario_name = "test_w_storage_starting_soc"
3✔
1264
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1265

1266
    def test_example_test_w_nonfuel_emissions(self):
3✔
1267
        """
1268
        Check validation and objective function value of "test" example
1269
        :return:
1270
        """
1271
        scenario_name = "test_w_nonfuel_emissions"
3✔
1272
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1273

1274
    def test_example_test_new_solar_carbon_credits(self):
3✔
1275
        """
1276
        Check validation and objective function value of
1277
        "test_new_solar_carbon_credits" example
1278
        :return:
1279
        """
1280
        scenario_name = "test_new_solar_carbon_credits"
3✔
1281
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1282

1283
    def test_performance_standard_carbon_credits(self):
3✔
1284
        """
1285
        Check validation and objective function value of "test_performance_standard" example
1286
        :return:
1287
        """
1288
        scenario_name = "test_performance_standard_carbon_credits"
3✔
1289
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1290

1291
    def test_example_test_new_solar_carbon_tax_w_carbon_credits(self):
3✔
1292
        """
1293
        Check validation and objective function value of
1294
        "test_new_solar_carbon_tax_w_carbon_credits" example
1295
        :return:
1296
        """
1297
        scenario_name = "test_new_solar_carbon_tax_w_carbon_credits"
3✔
1298
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1299

1300
    def test_example_test_new_solar_carbon_credits_w_sell(self):
3✔
1301
        """
1302
        Check validation and objective function value of
1303
        "test_new_solar_carbon_credits_w_sell" example
1304
        The carbon credit price must be set higher than the cost of USE in this
1305
        example to incentivize the project to not run and generate credits.
1306
        :return:
1307
        """
1308
        scenario_name = "test_new_solar_carbon_credits_w_sell"
3✔
1309
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1310

1311
    def test_test_performance_standard_carbon_credits_w_cap_no_credits_mapping(self):
3✔
1312
        """
1313
        Check validation and objective function value of
1314
        "test_performance_standard_carbon_credits_w_cap_no_credits_mapping" example
1315
        :return:
1316
        """
1317
        scenario_name = (
3✔
1318
            "test_performance_standard_carbon_credits_w_cap_no_credits_mapping"
1319
        )
1320
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1321

1322
    def test_test_new_solar_carbon_credits_w_buy(self):
3✔
1323
        """
1324
        Check validation and objective function value of "test_new_solar_carbon_credits_w_buy" example
1325
        :return:
1326
        """
1327
        scenario_name = "test_new_solar_carbon_credits_w_buy"
3✔
1328
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1329

1330
    def test_test_new_solar_carbon_credits_w_buy_and_sell(self):
3✔
1331
        """
1332
        Check validation and objective function value of "test_new_solar_carbon_credits_w_buy_and_sell" example
1333
        :return:
1334
        """
1335
        scenario_name = "test_new_solar_carbon_credits_w_buy_and_sell"
3✔
1336
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1337

1338
    def test_example_single_stage_prod_cost_w_spinup_lookahead(self):
3✔
1339
        """
1340
        Check validation and objective function values of
1341
        "single_stage_prod_cost_w_spinup_lookahead" example
1342
        :return:
1343
        """
1344
        scenario_name = "single_stage_prod_cost_w_spinup_lookahead"
3✔
1345
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1346

1347
    def test_example_test_tx_targets_max(self):
3✔
1348
        """
1349
        Check validation and objective function value of
1350
        "test_example_test_tx_targets_max"
1351
        example
1352
        :return:
1353
        """
1354
        scenario_name = "test_tx_targets_max"
3✔
1355
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1356

1357
    def test_example_ra_toolkit_monte_carlo(self):
3✔
1358
        """
1359
        Check validation and objective function values of
1360
        "ra_toolkit_monte_carlo" example
1361
        :return:
1362
        """
1363
        scenario_name = "ra_toolkit_monte_carlo"
3✔
1364
        self.validate_and_test_example_generic(
3✔
1365
            scenario_name=scenario_name, skip_validation=True
1366
        )
1367

1368
    def test_example_ra_toolkit_sync(self):
3✔
1369
        """
1370
        Check validation and objective function values of
1371
        "ra_toolkit_sync" example
1372
        :return:
1373
        """
1374
        scenario_name = "ra_toolkit_sync"
3✔
1375
        self.validate_and_test_example_generic(
3✔
1376
            scenario_name=scenario_name, skip_validation=True
1377
        )
1378

1379
    def test_example_2periods_nuclear_var_cost_by_period_same(self):
3✔
1380
        """
1381
        Check validation and objective function value of "2periods_nuclear_var_cost_by_period_same" example
1382
        :return:
1383
        """
1384
        scenario_name = "2periods_nuclear_var_cost_by_period_same"
3✔
1385
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1386

1387
    def test_example_2periods_nuclear_var_cost_by_period_diff(self):
3✔
1388
        """
1389
        Check validation and objective function value of
1390
        "2periods_nuclear_var_cost_by_period_diff" example
1391
        :return:
1392
        """
1393
        scenario_name = "2periods_nuclear_var_cost_by_period_diff"
3✔
1394
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1395

1396
    def test_example_ra_toolkit_sync_single_year(self):
3✔
1397
        """
1398
        Check validation and objective function values of
1399
        "ra_toolkit_sync_single_year" example
1400
        :return:
1401
        """
1402
        scenario_name = "ra_toolkit_sync_single_year"
3✔
1403
        self.validate_and_test_example_generic(
3✔
1404
            scenario_name=scenario_name, skip_validation=True
1405
        )
1406

1407
    def test_test_performance_standard_power(self):
3✔
1408
        """
1409
        Check validation and objective function values of "test_performance_standard_power" example
1410
        :return:
1411
        """
1412
        scenario_name = "test_performance_standard_power"
3✔
1413
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1414

1415
    def test_test_performance_standard_both(self):
3✔
1416
        """
1417
        Check validation and objective function values of "test_performance_standard_both" example
1418
        :return:
1419
        """
1420
        scenario_name = "test_performance_standard_both"
3✔
1421
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1422

1423
    def test_test_new_instantaneous_penetration(self):
3✔
1424
        """
1425
        Check validation and objective function value of "test_new_instantaneous_penetration" example
1426
        :return:
1427
        """
1428

1429
        scenario_name = "test_new_instantaneous_penetration"
3✔
1430
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1431

1432
    def test_hydro_system_exog_elev(self):
3✔
1433
        """
1434
        Check validation and objective function value of "hydro_system" example
1435
        :return:
1436
        """
1437

1438
        scenario_name = "hydro_system_exog_elev"
3✔
1439
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1440

1441
    def test_hydro_system_exog_elev_w_travel_time(self):
3✔
1442
        """
1443
        Check validation and objective function value of "hydro_system" example
1444
        :return:
1445
        """
1446

1447
        scenario_name = "hydro_system_exog_elev_w_travel_time"
3✔
1448
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1449

1450
    def test_test_tx_flow_w_simflow(self):
3✔
1451
        """
1452
        Check validation and objective function value of "test_tx_flow_w_simflow" example
1453
        :return:
1454
        """
1455

1456
        scenario_name = "test_tx_flow_w_simflow"
3✔
1457
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1458

1459
    def test_example_ra_toolkit_sync_single_year_w_hydro_instead_of_weather_profile(
3✔
1460
        self,
1461
    ):
1462
        """
1463
        Check validation and objective function values of
1464
        "ra_toolkit_sync_single_year_w_hydro_instead_of_weather_profile" example
1465
        :return:
1466
        """
1467
        scenario_name = "ra_toolkit_sync_single_year_w_hydro_instead_of_weather_profile"
3✔
1468
        self.validate_and_test_example_generic(
3✔
1469
            scenario_name=scenario_name, skip_validation=True
1470
        )
1471

1472
    def test_example_2periods_new_build_2zones_loadcomponents(self):
3✔
1473
        """
1474
        Check validation and objective function value of
1475
        "2periods_new_build_2zones_loadcomponents" example
1476
        :return:
1477
        """
1478
        scenario_name = "2periods_new_build_2zones_loadcomponents"
3✔
1479
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1480

1481
    def test_example_2periods_nuclear_var_cost_by_timepoint_same(self):
3✔
1482
        """
1483
        Check validation and objective function value of
1484
        "2periods_nuclear_var_cost_by_timepoint_same" example
1485
        :return:
1486
        """
1487
        scenario_name = "2periods_nuclear_var_cost_by_timepoint_same"
3✔
1488
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1489

1490
    def test_example_2periods_nuclear_var_cost_by_timepoint_diff(self):
3✔
1491
        """
1492
        Check validation and objective function value of
1493
        "2periods_nuclear_var_cost_by_timepoint_diff" example
1494
        :return:
1495
        """
1496
        scenario_name = "2periods_nuclear_var_cost_by_timepoint_diff"
3✔
1497
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1498

1499
    def test_example_test_w_storage_wind_as_energy(self):
3✔
1500
        """
1501
        Check validation and objective function value of
1502
        "test_w_storage_wind_as_energy" example
1503
        :return:
1504
        """
1505
        scenario_name = "test_w_storage_wind_as_energy"
3✔
1506
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1507

1508
    def test_example_test_w_hydro_no_reserves(self):
3✔
1509
        """
1510
        Check validation and objective function value of
1511
        "test_w_hydro_no_reserves"
1512
        example
1513
        :return:
1514
        """
1515
        scenario_name = "test_w_hydro_no_reserves"
3✔
1516
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1517

1518
    def test_example_test_w_hydro_as_energy_no_reserves(self):
3✔
1519
        """
1520
        Check validation and objective function value of
1521
        "test_w_hydro_as_energy_no_reserves"
1522
        example
1523
        :return:
1524
        """
1525
        scenario_name = "test_w_hydro_as_energy_no_reserves"
3✔
1526
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1527

1528
    def test_example_test_w_lf(self):
3✔
1529
        """
1530
        Check validation and objective function value of
1531
        "test_w_lf" example
1532
        :return:
1533
        """
1534
        scenario_name = "test_w_lf"
3✔
1535
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1536

1537
    def test_example_test_w_lf_w_demand_charges(self):
3✔
1538
        """
1539
        Check validation and objective function value of
1540
        "test_w_lf_w_demand_charges" example
1541
        :return:
1542
        """
1543
        scenario_name = "test_w_lf_w_demand_charges"
3✔
1544
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1545

1546
    def test_example_test_w_lf_only(self):
3✔
1547
        """
1548
        Check validation and objective function value of
1549
        "test_w_lf_only" example
1550
        :return:
1551
        """
1552
        scenario_name = "test_w_lf_only"
3✔
1553
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1554

1555
    def test_example_test_w_lf_only_and_prices(self):
3✔
1556
        """
1557
        Check validation and objective function value of
1558
        "test_w_lf_only_and_prices" example
1559
        :return:
1560
        """
1561
        scenario_name = "test_w_lf_only_and_prices"
3✔
1562
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1563

1564
    def test_example_test_w_lf_only_energy_potential_limit(self):
3✔
1565
        """
1566
        Check validation and objective function value of
1567
        "test_w_lf_only_energy_potential_limit" example
1568
        :return:
1569
        """
1570
        scenario_name = "test_w_lf_only_energy_potential_limit"
3✔
1571
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1572

1573
    def test_example_test_w_hydro_as_slice_candidate(self):
3✔
1574
        """
1575
        Check validation and objective function value of
1576
        "test_w_hydro_as_slice_candidate"
1577
        example
1578
        :return:
1579
        """
1580
        scenario_name = "test_w_hydro_as_slice_candidate"
3✔
1581
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1582

1583
    def test_example_test_w_energy_products(self):
3✔
1584
        """
1585
        Check validation and objective function value of
1586
        "test_w_lf_only_and_prices" example
1587
        :return:
1588
        """
1589
        scenario_name = "test_w_energy_products"
3✔
1590
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1591

1592
    def test_example_test_w_energy_products_group_limits(self):
3✔
1593
        """
1594
        Check validation and objective function value of
1595
        "test_w_lf_only_and_prices" example
1596
        :return:
1597
        """
1598
        scenario_name = "test_w_energy_products_group_limits"
3✔
1599
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1600

1601
    def test_example_2periods_new_build_generic_policy(self):
3✔
1602
        """
1603
        Check validation and objective function value of
1604
        "2periods_new_build_generic_policy" example
1605
        :return:
1606
        """
1607
        scenario_name = "2periods_new_build_generic_policy"
3✔
1608
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1609

1610
    def test_open_data(self):
3✔
1611
        """
1612
        Check validation and objective function value of "open_data" example
1613
        :return:
1614
        """
1615

1616
        scenario_name = "open_data"
3✔
1617
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1618

1619
    def test_hydro_system_exog_elev_w_travel_time_and_max_halfday_flows(self):
3✔
1620
        """
1621
        :return:
1622
        """
1623

1624
        scenario_name = "hydro_system_exog_elev_w_travel_time_and_max_halfday_flows"
3✔
1625
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1626

1627
    def test_hydro_system_w_ramp_limits(self):
3✔
1628
        """
1629
        :return:
1630
        """
1631

1632
        scenario_name = "hydro_system_w_ramp_limits"
3✔
1633
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1634

1635
    def test_test_w_bt_hrz_avl(self):
3✔
1636
        """
1637
        :return:
1638
        """
1639

1640
        scenario_name = "test_w_bt_hrz_avl"
3✔
1641
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1642

1643
    def test_hydro_system_exog_elev_w_gen_ramp_limits(self):
3✔
1644
        """ """
1645
        scenario_name = "hydro_system_exog_elev_w_gen_ramp_limits"
3✔
1646
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1647

1648
    def test_dsm_examples(self):
3✔
1649
        scenario_name = "dsm_examples"
3✔
1650
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1651

1652
    def test_example_test_w_hydro_ramp_limits(self):
3✔
1653
        """
1654
        Check validation and objective function value of
1655
        "test_w_hydro_ramp_limits" example
1656
        :return:
1657
        """
1658
        scenario_name = "test_w_hydro_ramp_limits"
3✔
1659
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1660

1661
    def test_example_2periods_new_build_generic_policy_recs(self):
3✔
1662
        """
1663
        Check validation and objective function value of
1664
        "2periods_new_build_rps_recs" example
1665
        :return:
1666
        """
1667
        scenario_name = "2periods_new_build_generic_policy_recs"
3✔
1668
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1669

1670
    def test_example_test_markets_w_tmp_total_limits(self):
3✔
1671
        """
1672
        Check validation and objective function value of "test" example
1673
        :return:
1674
        """
1675
        scenario_name = "test_markets_w_tmp_total_limits"
3✔
1676
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1677

1678
    def test_example_test_markets_w_prd_total_limits(self):
3✔
1679
        """
1680
        Check validation and objective function value of "test" example
1681
        :return:
1682
        """
1683
        scenario_name = "test_markets_w_prd_total_limits"
3✔
1684
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1685

1686
    def test_example_test_new_build_storage_losses_limit(self):
3✔
1687
        """
1688
        Check validation and objective function value of
1689
        "test_new_build_storage_losses_limit" example
1690
        :return:
1691
        """
1692

1693
        scenario_name = "test_new_build_storage_losses_limit"
3✔
1694
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1695

1696
    def test_example_test_carbon_credits_purchase_limits(self):
3✔
1697
        """
1698
        Check validation and objective function value of
1699
        "test_carbon_credits_purchase_limits" example
1700
        :return:
1701
        """
1702

1703
        scenario_name = "test_carbon_credits_purchase_limits"
3✔
1704
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1705

1706
    def test_example_test_inertia_reserves(self):
3✔
1707
        """
1708
        Check validation and objective function value of
1709
        "test_new_build_storage_losses_limit" example
1710
        :return:
1711
        """
1712

1713
        scenario_name = "test_inertia_reserves"
3✔
1714
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1715

1716
    def test_test_w_no_prj_av_sid_specified(self):
3✔
1717
        """
1718
        Check validation and objective function value of
1719
        "test_w_no_prj_av_sid_specified" example
1720
        :return:
1721
        """
1722

1723
        scenario_name = "test_w_no_prj_av_sid_specified"
3✔
1724
        self.validate_and_test_example_generic(scenario_name=scenario_name)
3✔
1725

1726
    @classmethod
3✔
1727
    def tearDownClass(cls):
3✔
1728
        os.remove(DB_PATH)
3✔
1729
        for temp_file_ext in ["-shm", "-wal"]:
3✔
1730
            temp_file = "{}{}".format(DB_PATH, temp_file_ext)
3✔
1731
            if os.path.exists(temp_file):
3✔
UNCOV
1732
                os.remove(temp_file)
×
1733

1734

1735
if __name__ == "__main__":
3✔
1736
    unittest.main()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc