Merge pull request #1262 from berndhahnebach/btprdev

bimtester
This commit is contained in:
Bernd Hahnebach
2021-01-15 10:59:45 +01:00
committed by GitHub
10 changed files with 221 additions and 181 deletions
@@ -15,8 +15,11 @@ def before_all(context):
# get from userdata
userdata = context.config.userdata
context.ifcbasename = userdata["ifcbasename"]
context.localedir = userdata.get("localedir")
context.ifcfile = userdata["ifcfile"]
context.ifcbasename = os.path.basename(
os.path.splitext(context.ifcfile)[0]
)
# do not break after a failed scenario
# https://community.osarch.org/discussion/comment/3328/#Comment_3328
+41 -10
View File
@@ -1,6 +1,9 @@
# TODO: improve layout, start with feature file path and beside button !!!!!
# TODO: all args should be passed to the gui,
# either pass them further to behave or make it possible to edit them before
# TODO: if browse widgets will be canceled, last QLineEdit should be restored
# TODO: keep path or file if in browse widget canceled
# TODO: make a frame around features direcory chooser and
# use features path from ifc button
import os
@@ -17,7 +20,8 @@ class GuiWidgetBimTester(QtWidgets.QWidget):
self,
featurespath="",
ifcfile="",
get_featurepath_from_ifcpath=False
get_featurepath_from_ifcpath=False,
args=[]
):
super(GuiWidgetBimTester, self).__init__()
@@ -36,6 +40,7 @@ class GuiWidgetBimTester(QtWidgets.QWidget):
self.initial_featurespath = featurespath
self.initial_ifcfile = ifcfile
self.get_featurepath_from_ifcpath = get_featurepath_from_ifcpath
self.args = args
# print(self.initial_featurespath)
# print(self.initial_ifcfile)
# print(self.get_featurepath_from_ifcpath)
@@ -198,18 +203,42 @@ class GuiWidgetBimTester(QtWidgets.QWidget):
# **********************************************************
def run_bimtester(self):
print("Run BIMTester")
print("Run BIMTester by the GUI")
QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
# get features dir
if self.featuredirfromifc_cb.isChecked() is True:
the_features_path = os.path.dirname(os.path.realpath(
self.get_ifcfile()
))
ifcfile = self.get_ifcfile()
print(
"Make sure the feature files are beside "
"the ifc file in a directory named 'features'."
)
if ifcfile == "":
# os.path.realpath("") would return the cmd dir and not ""
print(
"No ifcfile given, "
"thus features files path will be set to ''."
)
the_features_path = ""
elif os.path.isfile(ifcfile) is not True:
# if ifcfile does not exist set features path to ""
print(
"The ifcfile does not exist, "
"thus features files path will be set to ''."
)
the_features_path = ""
else:
ifcfilepath = os.path.dirname(os.path.realpath(ifcfile))
if os.path.isdir(ifcfilepath):
the_features_path = ifcfilepath
else:
print(
"ifcfilepath does not exist, "
"thus features files path will be set to ''."
"this shold never happen, please debug. "
)
the_features_path = ""
else:
the_features_path = self.get_featurefilesdir()
print(the_features_path)
@@ -218,11 +247,13 @@ class GuiWidgetBimTester(QtWidgets.QWidget):
the_ifcfile = self.get_ifcfile()
print(the_ifcfile)
# overwrite the_features_path and ifcfile in args
patched_args = self.args
patched_args["featuresdir"] = the_features_path
patched_args["ifcfile"] = the_ifcfile
# run bimtester
status = run_all(
the_features_path,
the_ifcfile,
)
status = run_all(patched_args)
print(status)
QtWidgets.QApplication.restoreOverrideCursor()
+20 -17
View File
@@ -8,12 +8,16 @@ from .features.steps.utils import switch_locale
def generate_report(
adir=".",
report_dir=".",
use_report_folder=True,
report_file_name="",
html_template_file_path=""
report_file_name="report.json",
html_template_file_path="",
report_file=""
):
# TODO use far less parameter
# to be discussed with other devs
print("# Generating HTML reports now.")
# get locale path
@@ -32,23 +36,22 @@ def generate_report(
if html_template_file_path:
report_template_path = html_template_file_path
# get report file
report_dir = adir
if use_report_folder:
report_dir = os.path.join(adir, "report")
if not os.path.exists(report_dir):
return print("No report directory was found.")
if report_file_name:
report_path = os.path.join(report_dir, report_file_name)
# get report file and report dir
if report_file:
report_file = report_file
report_dir = os.path.dirname(report_file)
else:
report_path = os.path.join(report_dir, "report.json")
# print(report_path)
if not os.path.exists(report_path):
return print("No report data was found.")
if use_report_folder:
report_dir = os.path.join(report_dir, "report")
report_file = os.path.join(report_dir, report_file_name)
# print(report_file)
if not os.path.isdir(report_dir):
return print("Report directory does not exist.")
if not os.path.isfile(report_file):
return print("Report file does not exist.")
# read json report and create html report for each feature
report = json.loads(open(report_path).read())
report = json.loads(open(report_file).read())
for feature in report:
file_name = os.path.basename(feature["location"]).split(":")[0]
data = {
+115 -131
View File
@@ -1,11 +1,13 @@
import behave.formatter.pretty # Needed for pyinstaller to package it
import fileinput
import os
import shutil
import sys
import tempfile
import webbrowser
from behave.__main__ import main as behave_main
# TODO: if the ifc file name or path contains special character
# like German Umlaute behave gives an error
# get bimtester source code module path
@@ -26,29 +28,106 @@ def get_resource_path(relative_path):
def run_tests(args):
if not get_features(args):
print("No features could be found to check.")
print("# Run tests.")
report_file = os.path.join("report", "report.json")
if "copyintemprun" in args and args["copyintemprun"] is True:
print("copyintemprun")
is_copyintemprun = True
args, copy_base_path = copy_intmp_tests(args)
features_path = os.path.join(copy_base_path, "features")
report_file = os.path.join(copy_base_path, report_file)
else:
print("No copyintemprun")
is_copyintemprun = False
if not get_features(args):
print("No features could be found to check.")
return False
features_path = get_resource_path("features")
# get behave args
behave_args = get_behave_args(args, features_path, report_file)
# run tests
if behave_args != []:
run_behave(behave_args)
else:
print("Error, not able to run behave because of empty behave args.")
return False
behave_args = [get_resource_path("features")]
if is_copyintemprun is True:
return report_file
else:
return True
def get_behave_args(args, features_path, report_file):
if os.path.isdir(features_path):
behave_args = [features_path]
else:
return []
if os.path.isdir(locale_path):
behave_args.extend([
# path for translation files
# next two lines are one arg
"--define",
"localedir={}".format(locale_path)
])
else:
print(
"Error, translation locals path '{}' does not exist."
.format(locale_path)
)
if args["advanced_arguments"]:
behave_args.extend(args["advanced_arguments"].split())
elif not args["console"]:
if args["ifcfile"]:
behave_args.extend([
# next two lines are one arg
"--define",
"ifcfile={}".format(args["ifcfile"])
])
if args["path"]:
behave_args.extend([
# next two lines are one arg
"--define",
"path={}".format(args["path"])
])
if not args["console"]:
behave_args.extend([
# redirect prints in step methods
# if step fails some output is catched, thus might not be printed
# https://github.com/behave/behave/issues/346
"--no-capture",
# next two lines are one arg
"--format",
"json.pretty",
# report file, if relative, than relative to current shell path
# next two lines are one arg
"--outfile",
"report/report.json"
report_file,
])
behave_args.extend([
"--define",
"localedir={}".format(locale_path)
])
if args["ifcfile"]:
behave_args.extend(["--define", "ifcfile={}".format(args["ifcfile"])])
if args["path"]:
behave_args.extend(["--define", "path={}".format(args["path"])])
return behave_args
def run_behave(behave_args):
from json import dumps
print(dumps(behave_args, indent=4))
from behave.__main__ import main as behave_main
behave_main(behave_args)
print("# All tests are finished.")
return True
@@ -99,44 +178,9 @@ reset_runtime()
"""
# TODO: if the ifc file name or path contains special character
# like German Umlaute behave gives an error
def copy_intmp_tests(args={}):
def run_copyintmp_tests(args={}):
"""
run bimtester unit test in a temporary directory
features, steps and environment.py are copied to a temp directory
Keys of parameter args
----------------------
features: optional (ATM mandatory)
the path the features directory with feature files is in
ifcfile: optional (ATM mandatory)
the ifc file
advanced_arguments: optional
they will be directly passed to the behave call
the following differentiation has to be made here because the decision
if the ifc file path in the feature file will be changed or not
features and ifcfile are given:
the ifcfile in feature files is replaced
features only is given (TODO):
the ifcfile provided in the feature files is used
ifcfile only is given (TODO):
features = ifcfile directory
the ifcfile in feature files is replaced
none of both is given (TODO):
the current directory = features
the ifcfile provided in the feature files is used
TODO: if the above is implemented adapt signature of run_all
"""
print("# Copy features and steps to temp.")
from behave import __version__ as behave_version
# https://github.com/behave/behave/issues/871
@@ -147,6 +191,7 @@ def run_copyintmp_tests(args={}):
)
return False
# print(args)
# get the features_path, the dir where the feature files to test are in
if ("featuresdir" in args and args["featuresdir"] != ""):
is_features = True
@@ -164,15 +209,13 @@ def run_copyintmp_tests(args={}):
if ("ifcfile" in args and args["ifcfile"] != ""):
is_ifcfile = True
ifcfile = args["ifcfile"]
if os.path.isfile(ifcfile) is not True:
print("Error, the ifc file '{}' does not exist.".format(ifcfile))
return False
ifc_path = os.path.dirname(os.path.realpath(ifcfile))
if os.path.isdir(ifc_path) is False:
print("ifc path does not exist.")
return False
if os.path.isfile(ifcfile) is True:
ifc_filename = os.path.basename(ifcfile)
else:
print("Error, the ifc file '{}' does not exist.".format(ifcfile))
return False
else:
is_ifcfile = False
@@ -181,17 +224,16 @@ def run_copyintmp_tests(args={}):
if is_features is True and is_ifcfile is True:
print("features given, ifcfile given.")
# the ifcfile in feature files is replaced
elif is_features is False and is_ifcfile is True:
print("features given, ifcfile NOT given.")
# features = ifcfile directory
# the ifcfile in feature files is replaced
the_features_path = os.path.join(ifc_path, "features")
elif is_features is True and is_ifcfile is False:
print("features given, ifcfile NOT given.")
# the ifcfile provided in the feature files is used
# TODO What will be passed as ifcfile arg?
print("Not yet implemented.")
return False
@@ -199,6 +241,7 @@ def run_copyintmp_tests(args={}):
print("features NOT given, ifcfile NOT given.")
# the current directory = features
# the ifcfile provided in the feature files is used
# TODO What will be passed as ifcfile arg?
print("Not yet implemented.")
return False
@@ -223,7 +266,6 @@ def run_copyintmp_tests(args={}):
)
return False
os.mkdir(copy_base_path)
report_path = os.path.join(copy_base_path, "report")
copy_features_path = os.path.join(copy_base_path, "features")
# copy features path from bimtester source code
@@ -252,8 +294,7 @@ def run_copyintmp_tests(args={}):
# dirs_exist_ok=True
# )
# copy feature files and replace ifcpath in feature files
# replaceing is IMHO better than copy the ifc file which could be 500 MB
# copy feature files
feature_files = os.listdir(the_features_path)
# print(feature_files)
for feature_file in feature_files:
@@ -264,95 +305,38 @@ def run_copyintmp_tests(args={}):
os.path.join(the_features_path, feature_file),
cp_feature_file
)
# search the line
ff = open(cp_feature_file, "r")
lines = ff.readlines()
ff.close()
theline = ""
for line in lines:
if "* The IFC file" in line and "must be provided" in line:
theline = line
if ifc_filename is None:
ifc_filename = os.path.basename(theline.split('"')[1])
newifcline = (
' * The IFC file "{}" must be provided\n'
.format(os.path.join(ifc_path, ifc_filename))
)
# print(newifcline)
break
else:
print("The line which sets the ifc file to test was not found.")
newifcline = ""
# replace the line
if newifcline != "":
# https://stackoverflow.com/a/290494
for line in fileinput.input(cp_feature_file, inplace=True):
# the print replaces the line in the file
print(line.replace(theline, newifcline), end="")
# get behave args
behave_args = [copy_features_path]
behave_args.extend([
# redirect prints in step methods
# if step fails some output is catched, thus might not be printed
# https://github.com/behave/behave/issues/346
"--no-capture",
# next two lines are one arg
"--format",
"json.pretty",
# next two lines are one arg
"--outfile",
os.path.join(report_path, "report.json"),
# next two lines are one arg
"--define",
"ifcbasename={}".format(os.path.splitext(ifc_filename)[0]),
# next two lines are one arg
"--define",
"localedir={}".format(locale_path)
])
if "advanced_arguments" in args:
behave_args.extend(args["advanced_arguments"].split())
from json import dumps
print(dumps(behave_args, indent=4))
# run tests
from behave.__main__ import main as behave_main
behave_main(behave_args)
print("All tests are finished.")
return copy_base_path
return args, copy_base_path
def run_all(the_features_path, the_ifcfile):
def run_all(args):
print("# Run all.")
# run bimtester
runpath = run_copyintmp_tests({
"featuresdir": the_features_path,
"ifcfile": the_ifcfile
})
print(runpath)
report_file = run_tests(args)
print(report_file)
# check if it worked out well
if runpath is False:
if report_file is False:
print("BIMTester behave tests returned False.")
return False
if not os.path.isdir(runpath):
print("runpath does not exist. This should not happen. Debug")
if not os.path.isfile(report_file):
print("Report directory does not exist. This should not happen. Debug")
return False
# create html report and open in webbrowser
from .reports import generate_report
generate_report(runpath)
generate_report(report_file=report_file)
# get the feature files
feature_files = os.listdir(
os.path.join(the_features_path, "features")
os.path.join(args["featuresdir"], "features")
)
# print(feature_files)
for ff in feature_files:
webbrowser.open(os.path.join(
runpath,
"report",
os.path.dirname(report_file),
ff + ".html"
))
@@ -26,7 +26,7 @@ DATA;
#20=IFCDIRECTION((0.,1.));
#21=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,#9,#20);
#22=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Model',*,*,*,*,#21,$,.MODEL_VIEW.,$);
#23=IFCPROJECT('2iAYrakL9FABNNwZfj$CbO',#5,'Column',$,$,$,$,(#21),#19);
#23=IFCPROJECT('2iAYrakL9FABNNwZfj$CbO',#5,'BIMTester Example 1',$,$,$,$,(#21),#19);
#24=IFCDIRECTION((1.,0.));
#25=IFCCARTESIANPOINT((0.,0.));
#26=IFCAXIS2PLACEMENT2D(#25,#24);
@@ -26,7 +26,7 @@ DATA;
#20=IFCDIRECTION((0.,1.));
#21=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,#9,#20);
#22=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Model',*,*,*,*,#21,$,.MODEL_VIEW.,$);
#23=IFCPROJECT('2iAYrakL9FABNNwZfj$CbO',#5,'Column',$,$,$,$,(#21),#19);
#23=IFCPROJECT('2iAYrakL9FABNNwZfj$CbO',#5,'BIMTester Example 1',$,$,$,$,(#21),#19);
#24=IFCDIRECTION((1.,0.));
#25=IFCCARTESIANPOINT((0.,0.));
#26=IFCAXIS2PLACEMENT2D(#25,#24);
@@ -7,6 +7,9 @@ We need an IFC file
Scenario: Receiving a file
* The IFC file "myifc.ifc" must be provided
* The IFC file has been provided through an argument
* IFC data must use the IFC2X3 schema
Scenario: Project information
* The project name, code, or short identifier must be "BIMTester Example 1"
@@ -8,7 +8,9 @@ We need an IFC file
Scénario: Recevoir e fichier
# This step will not be translated ATM. ... Needs to be translated into Frensh
* The IFC file "myifc.ifc" must be provided
* The IFC file has been provided through an argument
* Les données IFC doivent utiliser le schéma IFC2X3
Scénario: Project information
* The project name, code, or short identifier must be "BIMTester Example 1"
@@ -9,7 +9,9 @@ Wir brauchen eine IFC-Datei
Szenario: Bereitstellen von IFC-Daten
# Dieser step wird aktuell nicht uebersetzt
* The IFC file "myifc.ifc" must be provided
* The IFC file has been provided through an argument
* Die IFC Daten müssen das IFC2X3 Schema benutzen
Szenario: Projektinformationen
* The project name, code, or short identifier must be "BIMTester Example 1"
+24 -12
View File
@@ -8,7 +8,12 @@ from bimtester import reports
from bimtester import run
def show_widget(features="", ifcfile="", get_featurepath_from_ifcpath=False):
def show_widget(
features="",
ifcfile="",
get_featurepath_from_ifcpath=False,
args=[]
):
import sys
from PySide2 import QtWidgets
@@ -19,7 +24,12 @@ def show_widget(features="", ifcfile="", get_featurepath_from_ifcpath=False):
app = QtWidgets.QApplication(sys.argv)
# Create and show the form
form = GuiWidgetBimTester(features, ifcfile, get_featurepath_from_ifcpath)
form = GuiWidgetBimTester(
features,
ifcfile,
get_featurepath_from_ifcpath,
args
)
form.show()
# Run the main Qt loop
@@ -58,6 +68,13 @@ if __name__ == "__main__":
),
default=""
)
parser.add_argument(
"-f",
"--feature",
type=str,
help="Specify a feature file to test",
default=""
)
parser.add_argument(
"-g",
"--gui",
@@ -67,13 +84,6 @@ if __name__ == "__main__":
"is triggered automaticly."
)
)
parser.add_argument(
"-f",
"--feature",
type=str,
help="Specify a feature file to test",
default=""
)
parser.add_argument(
"-i",
"--ifcfile",
@@ -135,14 +145,16 @@ if __name__ == "__main__":
elif args["report"]:
reports.generate_report()
elif args["gui"]:
args["copyintemprun"] = True
fea = args["featuresdir"]
ifc = args["ifcfile"]
if fea != "" and ifc != "":
show_widget(fea, ifc, False)
show_widget(fea, ifc, False, args)
elif fea == "" and ifc != "":
show_widget(fea, ifc, True)
show_widget(fea, ifc, True, args)
elif args["copyintemprun"]:
run.run_copyintmp_tests(args)
run.run_tests(args)
# TODO merge with else, but do not forget the tmp dir is not known
else:
run.run_tests(args)
if args["report_after_run"]: