Skip to content

Commit

Permalink
Moved get_xfoil. Enhanced PackageReader (better check for existence).
Browse files Browse the repository at this point in the history
  • Loading branch information
christophe-david committed Jan 17, 2022
1 parent dbd4727 commit c42545f
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 65 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/watchman_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
shell: bash

- name: Unit tests
run: pytest --no-cov src
run: pytest --no-cov src -c ./conftest.py
shell: bash

- name: Notebook tests
Expand Down
39 changes: 37 additions & 2 deletions src/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@

import os.path as pth
import sys
from typing import List
from platform import system
from shutil import which
from typing import List, Optional
from unittest.mock import Mock

import pytest
Expand All @@ -36,8 +38,41 @@
CONFIGURATION_FILE_PATH = pth.join(DATA_FOLDER_PATH, "sellar.yml")


@pytest.fixture(autouse=True)
def no_xfoil_skip(request, xfoil_path):
"""
Use @pytest.mark.skip_if_no_xfoil() before a test to skip it if xfoil_path
fixture returns None and OS is not Windows.
"""
if request.node.get_closest_marker("skip_if_no_xfoil"):
if xfoil_path is None and system() != "Windows":
pytest.skip("No XFOIL executable available")


@pytest.fixture
def xfoil_path() -> Optional[str]:
"""
On a system that is not Windows, a XFOIL executable with name "xfoil" can
be put in "<project_root>/tests/xfoil_exe/".
In this case, this fixture will return its path.
:return: The path of the XFOIL executable
"""
if system() == "Windows":
# On Windows, we use the embedded executable
return None

path = pth.abspath(pth.join("tests/xfoil_exe", "xfoil"))
if pth.exists(path):
# If there is a local xfoil, use it
return path

# Otherwise, use one that is in PATH, if it exists
return which("xfoil")


@pytest.fixture
def plugin_root_path():
def plugin_root_path() -> str:
"""Returns the path to dummy plugins, for check purpose."""
return pth.abspath("tests/dummy_plugins")

Expand Down
12 changes: 11 additions & 1 deletion src/fastoad/_utils/resource_management/contents.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def __init__(self, package_name: str):
:param package_name:
"""
self.is_package = False
self.exists = True
self.is_module = False
self.has_error = False
self._contents = []
Expand All @@ -49,7 +50,16 @@ def package_name(self, package_name):
except TypeError:
self.is_module = True
except ModuleNotFoundError:
pass
# Either the indicated package does not exist, or it is a file with no extension.
# We want to ensure existence to correctly set self.exists.
if "." in package_name:
parent_package_name, module_name = package_name.rsplit(".", 1)
parent_package = PackageReader(parent_package_name)
if parent_package.is_package and module_name in parent_package.contents:
self.exists = True
else:
# Here we assume non-existence
self.exists = False
except Exception: # pylint: disable = W0703
# Here we catch any Python error that may happen when reading the loaded code.
# Thus, we ensure to not break the application if a module is incorrectly written.
Expand Down
18 changes: 5 additions & 13 deletions src/fastoad/models/aerodynamics/external/xfoil/tests/test_xfoil.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Test module for XFOIL component
"""
# This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
# Copyright (C) 2021 ONERA & ISAE-SUPAERO
# Copyright (C) 2022 ONERA & ISAE-SUPAERO
# FAST is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
Expand All @@ -18,24 +18,18 @@

import os.path as pth
import shutil
from platform import system

import pytest
from openmdao.core.indepvarcomp import IndepVarComp

from fastoad._utils.testing import run_system
from tests.xfoil_exe.get_xfoil import get_xfoil_path
from ..xfoil_polar import DEFAULT_2D_CL_MAX, XfoilPolar

XFOIL_RESULTS = pth.join(pth.dirname(__file__), "results")

xfoil_path = None if system() == "Windows" else get_xfoil_path()


@pytest.mark.skipif(
system() != "Windows" and xfoil_path is None, reason="No XFOIL executable available"
)
def test_compute():
@pytest.mark.skip_if_no_xfoil()
def test_compute(xfoil_path):
"""Tests a simple XFOIL run"""

if pth.exists(XFOIL_RESULTS):
Expand Down Expand Up @@ -80,10 +74,8 @@ def test_compute():
assert pth.exists(pth.join(XFOIL_RESULTS, "polar_result.txt"))


@pytest.mark.skipif(
system() != "Windows" and xfoil_path is None, reason="No XFOIL executable available"
)
def test_compute_with_provided_path():
@pytest.mark.skip_if_no_xfoil()
def test_compute_with_provided_path(xfoil_path):
"""Test that option "use_exe_path" works"""
ivc = IndepVarComp()
ivc.add_output("xfoil:reynolds", 18000000)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Test module for aerodynamics groups
"""
# This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
# Copyright (C) 2021 ONERA & ISAE-SUPAERO
# Copyright (C) 2022 ONERA & ISAE-SUPAERO
# FAST is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
Expand All @@ -15,18 +15,14 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.

import os.path as pth
from platform import system

import pytest
from pytest import approx

from fastoad._utils.testing import run_system
from fastoad.io import VariableIO
from tests.xfoil_exe.get_xfoil import get_xfoil_path
from ..aerodynamics_landing import AerodynamicsLanding

xfoil_path = None if system() == "Windows" else get_xfoil_path()


def get_indep_var_comp(var_names):
"""Reads required input data and returns an IndepVarcomp() instance"""
Expand All @@ -36,10 +32,8 @@ def get_indep_var_comp(var_names):
return ivc


@pytest.mark.skipif(
system() != "Windows" and xfoil_path is None, reason="No XFOIL executable available"
)
def test_aerodynamics_landing_with_xfoil():
@pytest.mark.skip_if_no_xfoil()
def test_aerodynamics_landing_with_xfoil(xfoil_path):
"""Tests AerodynamicsHighSpeed"""
input_list = [
"data:TLAR:approach_speed",
Expand Down
5 changes: 1 addition & 4 deletions src/fastoad/module_management/_bundle_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ def _install_python_package(self, package_name: str) -> Tuple[Set[Bundle], Set[s
failed = set()

package = PackageReader(package_name)
if package.has_error:
if package.has_error or not package.exists:
failed.add(package_name)
elif package.is_package:
# It is a package, let's explore it.
Expand All @@ -362,9 +362,6 @@ def _install_python_package(self, package_name: str) -> Tuple[Set[Bundle], Set[s
sub_bundles, sub_failed = self._install_python_package(item_package)
bundles.update(sub_bundles)
failed.update(sub_failed)
elif not package.is_module:
# Does not exist.
failed.add(package_name)

return bundles, failed

Expand Down
5 changes: 4 additions & 1 deletion tests/xfoil_exe/__init__.py → tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
# Copyright (C) 2020 ONERA & ISAE-SUPAERO
# Copyright (C) 2022 ONERA & ISAE-SUPAERO
# FAST is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
Expand All @@ -10,3 +10,6 @@
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

# pylint: disable=unused-import
from src.conftest import no_xfoil_skip, xfoil_path # noqa: F401
17 changes: 9 additions & 8 deletions tests/integration_tests/oad_process/test_oad_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Test module for Overall Aircraft Design process
"""
# This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
# Copyright (C) 2021 ONERA & ISAE-SUPAERO
# Copyright (C) 2022 ONERA & ISAE-SUPAERO
# FAST is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
Expand Down Expand Up @@ -34,13 +34,10 @@
_IConfigurationModifier,
)
from tests import root_folder_path
from tests.xfoil_exe.get_xfoil import get_xfoil_path

DATA_FOLDER_PATH = pth.join(pth.dirname(__file__), "data")
RESULTS_FOLDER_PATH = pth.join(pth.dirname(__file__), "results")

xfoil_path = None if system() == "Windows" else get_xfoil_path()


@pytest.fixture(scope="module")
def cleanup():
Expand Down Expand Up @@ -75,12 +72,13 @@ def test_oad_process(cleanup):
_check_weight_performance_loop(problem)


def test_non_regression_breguet(cleanup):
def test_non_regression_breguet(cleanup, xfoil_path):
run_non_regression_test(
"oad_process_breguet.yml",
"CeRAS01_legacy_breguet_result.xml",
"non_regression_breguet",
use_xfoil=True,
xfoil_path=xfoil_path,
)


Expand Down Expand Up @@ -114,12 +112,13 @@ class XFOILConfigurator(_IConfigurationModifier):
"""Overwrite XFOIL usage setting of configuration file"""

use_xfoil: bool
xfoil_path: str = None

def modify(self, problem: om.Problem):
if self.use_xfoil and (system() == "Windows" or xfoil_path):
if self.use_xfoil and (system() == "Windows" or self.xfoil_path):
problem.model.aerodynamics_landing._OPTIONS["use_xfoil"] = True
if system() != "Windows":
problem.model.aerodynamics_landing._OPTIONS["xfoil_exe_path"] = xfoil_path
problem.model.aerodynamics_landing._OPTIONS["xfoil_exe_path"] = self.xfoil_path
# BTW we narrow computed alpha range for sake of CPU time
problem.model.aerodynamics_landing._OPTIONS["xfoil_alpha_min"] = 16.0
problem.model.aerodynamics_landing._OPTIONS["xfoil_alpha_max"] = 22.0
Expand All @@ -130,6 +129,7 @@ def run_non_regression_test(
legacy_result_file,
result_dir,
use_xfoil=False,
xfoil_path=None,
global_tolerance=1e-2,
vars_to_check=None,
specific_tolerance=5.0e-3,
Expand All @@ -141,6 +141,7 @@ def run_non_regression_test(
:param legacy_result_file: reference data for inputs and outputs
:param result_dir: relative name, folder will be in RESULTS_FOLDER_PATH
:param use_xfoil: if True, XFOIL computation will be activated
:param xfoil_path: used if use_xfoil==True
:param vars_to_check: variables that will be concerned by specific_tolerance
:param specific_tolerance: test will fail if absolute relative error between computed and
reference values is beyond this value for variables in vars_to_check
Expand All @@ -155,7 +156,7 @@ def run_non_regression_test(
api.generate_configuration_file(configuration_file_path) # just ensure folders are created...
shutil.copy(pth.join(DATA_FOLDER_PATH, conf_file), configuration_file_path)
configurator = FASTOADProblemConfigurator(configuration_file_path)
configurator._set_configuration_modifier(XFOILConfigurator(use_xfoil))
configurator._set_configuration_modifier(XFOILConfigurator(use_xfoil, xfoil_path))

# Generation of inputs ----------------------------------------
ref_inputs = pth.join(DATA_FOLDER_PATH, legacy_result_file)
Expand Down
26 changes: 0 additions & 26 deletions tests/xfoil_exe/get_xfoil.py

This file was deleted.

0 comments on commit c42545f

Please sign in to comment.