Skip to content

Commit

Permalink
Improving Code Coverage (and doing cleanup) (#634)
Browse files Browse the repository at this point in the history
  • Loading branch information
john-science committed Apr 22, 2022
1 parent 658900f commit 155aeab
Show file tree
Hide file tree
Showing 16 changed files with 140 additions and 73 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ bin/*
/bin
dist/
dist-*/
doc/*.png
*.png
doc/_build
doc/user/tutorials
doc/tutorials/anl-afci-177*
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,6 @@ only use third-party Python libraries that have MIT or BSD licenses.
.. |Build Status| image:: https://github.com/terrapower/armi/actions/workflows/unittests.yaml/badge.svg?branch=master
:target: https://github.com/terrapower/armi/actions/workflows/unittests.yaml

.. |Code Coverage| image:: https://coveralls.io/repos/github/terrapower/armi/badge.svg?branch=master&kill_cache=2
.. |Code Coverage| image:: https://coveralls.io/repos/github/terrapower/armi/badge.svg?branch=master&kill_cache=3
:target: https://coveralls.io/github/terrapower/armi?branch=master

2 changes: 1 addition & 1 deletion armi/bookkeeping/report/reportingUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ def setNeutronBalancesReport(core):
report.NEUT_LOSS,
)

runLog.info(report.ALL[report.NEUT_PROD]) # TODO: print in "lite"
runLog.info(report.ALL[report.NEUT_PROD])
runLog.info(report.ALL[report.NEUT_LOSS])


Expand Down
79 changes: 66 additions & 13 deletions armi/bookkeeping/report/tests/test_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,6 @@ def test_setData(self):
self.assertEqual(filled_instance["banana_2"], ["sundae", "vanilla"])
self.assertEqual(filled_instance["banana_3"], ["sundae", "chocolate"])

def test_printReports(self):
"""testing printReports method"""
repInt = reportInterface.ReportInterface(None, None)
rep = repInt.printReports()

self.assertIn("REPORTS BEGIN", rep)
self.assertIn("REPORTS END", rep)

def test_writeReports(self):
"""Test writing html reports."""
repInt = reportInterface.ReportInterface(None, None)
repInt.writeReports()

def test_reactorSpecificReporting(self):
"""Test a number of reporting utils that require reactor/core information"""
o, r = loadTestReactor()
Expand Down Expand Up @@ -138,5 +125,71 @@ def test_reactorSpecificReporting(self):
self.assertTrue(len(mock._outputStream) == 0)


class TestReportInterface(unittest.TestCase):
def test_printReports(self):
"""testing printReports method"""
repInt = reportInterface.ReportInterface(None, None)
rep = repInt.printReports()

self.assertIn("REPORTS BEGIN", rep)
self.assertIn("REPORTS END", rep)

def test_writeReports(self):
"""Test writing html reports."""
repInt = reportInterface.ReportInterface(None, None)
repInt.writeReports()

def test_distributableReportInt(self):
repInt = reportInterface.ReportInterface(None, None)
self.assertEqual(repInt.distributable(), 4)

def test_interactBOLReportInt(self):
o, r = loadTestReactor()
repInt = reportInterface.ReportInterface(r, o.cs)

with mockRunLogs.BufferLog() as mock:
repInt.interactBOL()
self.assertIn("Writing assem layout", mock._outputStream)
self.assertIn("BOL Assembly", mock._outputStream)
self.assertIn("wetMass", mock._outputStream)
self.assertIn("moveable plenum", mock._outputStream)

def test_interactEveryNode(self):
o, r = loadTestReactor()
repInt = reportInterface.ReportInterface(r, o.cs)

with mockRunLogs.BufferLog() as mock:
repInt.interactEveryNode(0, 0)
self.assertIn("Cycle 0", mock._outputStream)
self.assertIn("node 0", mock._outputStream)
self.assertIn("keff=", mock._outputStream)

def test_interactBOC(self):
o, r = loadTestReactor()
repInt = reportInterface.ReportInterface(r, o.cs)

self.assertEqual(repInt.fuelCycleSummary["bocFissile"], 0.0)
repInt.interactBOC(1)
self.assertEqual(repInt.fuelCycleSummary["bocFissile"], 0.0)

def test_interactEOC(self):
o, r = loadTestReactor()
repInt = reportInterface.ReportInterface(r, o.cs)

with mockRunLogs.BufferLog() as mock:
repInt.interactEOC(0)
self.assertIn("Cycle 0", mock._outputStream)
self.assertIn("TIMER REPORTS", mock._outputStream)

def test_interactEOL(self):
o, r = loadTestReactor()
repInt = reportInterface.ReportInterface(r, o.cs)

with mockRunLogs.BufferLog() as mock:
repInt.interactEOL()
self.assertIn("Comprehensive Core Report", mock._outputStream)
self.assertIn("Assembly Area Fractions", mock._outputStream)


if __name__ == "__main__":
unittest.main()
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ DATASET=A.MCC2
22 CM2455 7 202.55000
22 CM2465 7 202.55000
22 CM2475 7 202.55000
01 ARMI generated \\albert\apps\dev\mc2\2.0\mc2.exe case for caseTitle mrtTWRP600v6rev3OS, block <twrp starter fuel B0064F at A8009F XS: B BU GP: A>
01 ARMI generated \\path\to\mc2\2.0\mc2.exe case for caseTitle mrtTWRP600v6rev3OS, block <twrp starter fuel B0064F at A8009F XS: B BU GP: A>
DATASET=A.DLAY
01 CREATE VERSION VI DLAYXS FILE FROM FUELI
03 1 0 0 0 0
Expand Down
4 changes: 2 additions & 2 deletions armi/nuclearDataIO/tests/library-file-generation/mc2v3-AA.inp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ $control
l_gamma = T
/
$library
c_mcclibdir ="\\albert\apps\prod\mc2\3.2.2\libraries\endfb-vii.0\lib.mcc.e70"
c_gammalibdir = "\\albert\apps\prod\mc2\3.2.2\libraries\endfb-vii.0\lib.gamma.e70"
c_mcclibdir ="\\path\to\mc2\3.2.2\libraries\endfb-vii.0\lib.mcc.e70"
c_gammalibdir = "\\path\to\mc2\3.2.2\libraries\endfb-vii.0\lib.gamma.e70"
/
$material
t_composition(:,1) = U235_7 "U235AA" 1.00000E-03 873.000 ! Fuel
Expand Down
4 changes: 2 additions & 2 deletions armi/nuclearDataIO/tests/library-file-generation/mc2v3-AB.inp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ $control
l_gamma = T
/
$library
c_mcclibdir ="\\albert\apps\prod\mc2\3.2.2\libraries\endfb-vii.0\lib.mcc.e70"
c_gammalibdir = "\\albert\apps\prod\mc2\3.2.2\libraries\endfb-vii.0\lib.gamma.e70"
c_mcclibdir ="\\path\to\mc2\3.2.2\libraries\endfb-vii.0\lib.mcc.e70"
c_gammalibdir = "\\path\to\mc2\3.2.2\libraries\endfb-vii.0\lib.gamma.e70"
/
$material
t_composition(:,1) = U235_7 "U235AB" 1.10000E-03 873.000 ! Fuel
Expand Down
2 changes: 2 additions & 0 deletions armi/physics/fuelCycle/tests/test_fuelHandlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,13 +523,15 @@ def test_buReducingAssemblyRotation(self):
newSettings = {"assemblyRotationStationary": True}
self.o.cs = self.o.cs.modified(newSettings=newSettings)
assem = self.o.r.core.getFirstAssembly(Flags.FUEL)

# apply dummy pin-level data to allow intelligent rotation
for b in assem.getBlocks(Flags.FUEL):
b.breakFuelComponentsIntoIndividuals()
b.initializePinLocations()
b.p.percentBuMaxPinLocation = 10
b.p.percentBuMax = 5
b.p.linPowByPin = list(reversed(range(b.getNumPins())))

addSomeDetailAssemblies(hist, [assem])
rotNum = b.getRotationNum()
fh.buReducingAssemblyRotation()
Expand Down
28 changes: 26 additions & 2 deletions armi/reactor/tests/test_zones.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
"""Test for Zones"""
# pylint: disable=missing-function-docstring,missing-class-docstring,abstract-method,protected-access
import copy
import unittest
import logging
import os
import unittest

from armi import runLog
from armi.reactor import assemblies
from armi.reactor import blueprints
from armi.reactor import geometry
Expand All @@ -27,6 +29,7 @@
from armi.reactor.flags import Flags
from armi.reactor.tests import test_reactors
from armi.settings.fwSettings import globalSettings
from armi.tests import mockRunLogs

THIS_DIR = os.path.dirname(__file__)

Expand Down Expand Up @@ -376,7 +379,28 @@ def test_createHotZones(self):
self.assertEqual(hotCount, 1)
self.assertEqual(normalCount, 2)

def test_zoneSummary(self):
o, r = test_reactors.loadTestReactor()

r.core.buildZones(o.cs)
daZones = r.core.zones

# make sure we have a couple of zones to test on
for name0 in ["ring-1-radial-shield-5", "ring-1-feed-fuel-5"]:
self.assertIn(name0, daZones.names)

with mockRunLogs.BufferLog() as mock:
runLog.LOG.startLog("test_zoneSummary")
runLog.LOG.setVerbosity(logging.INFO)

self.assertEqual("", mock._outputStream)

daZones.summary()

self.assertIn("Zone Summary", mock._outputStream)
self.assertIn("Zone Power", mock._outputStream)
self.assertIn("Zone Average Flow", mock._outputStream)


if __name__ == "__main__":
# import sys;sys.argv = ['', 'Zones_InReactor.test_buildRingZones']
unittest.main()
8 changes: 6 additions & 2 deletions armi/settings/caseSettings.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,13 @@ def _applyReadSettings(self, path=None):
if path:
self.path = path # can't set this before a chance to fail occurs

# TODO: At some point, much of the logging init will be moved to runLog, including this.
def initLogVerbosity(self):
"""Central location to init logging verbosity"""
"""
Central location to init logging verbosity
NOTE: This means that creating a Settings object sets the global logging
level of the entire code base.
"""
if context.MPI_RANK == 0:
runLog.setVerbosity(self["verbosity"])
else:
Expand Down
16 changes: 5 additions & 11 deletions armi/settings/settingsIO.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,17 +364,11 @@ def prompt(statement, question, *options):
import wx # pylint: disable=import-error

msg = statement + "\n\n\n" + question
if len(msg) < 300:
style = wx.CENTER
for opt in options:
style |= getattr(wx, opt)
dlg = wx.MessageDialog(None, msg, style=style)
else:
# for shame. Might make sense to move the styles stuff back into the
# Framework
from tparmi.gui.styles import dialogues
style = wx.CENTER
for opt in options:
style |= getattr(wx, opt)
dlg = wx.MessageDialog(None, msg, style=style)

dlg = dialogues.ScrolledMessageDialog(None, msg, "Prompt")
response = dlg.ShowModal()
dlg.Destroy()
if response == wx.ID_CANCEL:
Expand All @@ -401,7 +395,7 @@ def prompt(statement, question, *options):
if "NO" in responses:
responses.append("N")

# TODO: Using the logger is strange. Perhaps this is a rare use-case for bare print? Or something bespoke.
# Use the logger tools to handle user prompts (runLog supports this).
while response not in responses:
runLog.LOG.log("prompt", statement)
runLog.LOG.log("prompt", "{} ({}): ".format(question, ", ".join(responses)))
Expand Down
18 changes: 18 additions & 0 deletions armi/settings/tests/test_settingsIO.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,20 @@ def test_invalidFile(self):
)


class SettingsReaderTests(unittest.TestCase):
def setUp(self):
self.cs = settings.caseSettings.Settings()

def test_basicSettingsReader(self):
reader = settingsIO.SettingsReader(self.cs)

self.assertEqual(reader["numProcessors"], 1)
self.assertEqual(reader["nCycles"], 1)

self.assertFalse(getattr(reader, "filelessBP"))
self.assertEqual(getattr(reader, "path"), "")


class SettingsRenameTests(unittest.TestCase):
testSettings = [
setting.Setting(
Expand Down Expand Up @@ -124,6 +138,10 @@ def test_writeYaml(self):
self.cs.loadFromInputFile(self.filepathYaml)
self.assertEqual(self.cs["nCycles"], 55)

def test_errorSettingsWriter(self):
with self.assertRaises(ValueError):
_ = settingsIO.SettingsWriter(self.cs, "wrong")


class MockEntryPoint(entryPoint.EntryPoint):
name = "dummy"
Expand Down
34 changes: 4 additions & 30 deletions armi/utils/dynamicImporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,36 +21,11 @@
from armi import runLog


def _importModule(modules):
# Import the module containing the interface
try:
module = __import__(".".join(modules))
except:
runLog.error(
"Failed to dynamically import the module {}".format(".".join(modules))
)
raise
# recursively get attributes.
for subMod in modules[1:]:
# Traverse down the chain to the actual module
try:
module = getattr(module, subMod)
except:
runLog.error(
"Attempting to dynamically import subclasses has failed. \n"
"The module {} does not have `{}'".format(module, subMod)
)
raise
return module


def importModule(fullyQualifiedModule):
return _importModule(fullyQualifiedModule.split("."))


def importEntirePackage(module):
"""Load every module in a package"""
# TODO: this method may only work for a flat directory?
"""Load every module in a package
NOTE: this method may only work for a flat directory?
"""
modules = glob.glob(os.path.dirname(module.__file__) + "/*.py")
names = [os.path.basename(f)[:-3] for f in modules]
for name in names:
Expand All @@ -63,7 +38,6 @@ def getEntireFamilyTree(cls):
One large caveat is it can only locate subclasses that had been imported somewhere
Look to use importEntirePackage before searching for subclasses if not all children
are being found as expected.
"""
return cls.__subclasses__() + [
grandchildren
Expand Down
6 changes: 3 additions & 3 deletions doc/developer/reports.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Reports in ARMI
================
.. note:: The resulting report itself is an Html page with table of contents on the left.
.. note:: The resulting report itself is an HTML page with table of contents on the left.

ARMI provides the ability to make a variety of plots and tables describing the state of the reactor.
Also, with ARMI's variety of plugins, some plots/analysis could be plugin dependent. If you have certain plugins installed, some new
Expand Down Expand Up @@ -241,7 +241,7 @@ Here, only one label exists, so we only add one line for ``label[0]``. There are
In summary, to add multiple lines (say, for different assembly types on a Peak DPA plot), the label would be the assembly type and the data would be the dpa at the time for that type.
The ``uncertainty`` value --> which in general denotes an error bar on the graph---> would be None or 0, for each point if there is no uncertainty.

Html Elements
HTML Elements
-------------
One may also want to add just plain prose. To do this, Sections also allow for the addition of htmltree elements so you can add paragraphs,
divs, etc, as outlined in htmltree. These parts however will not be titled unless wrapped within a Section, and similarily will not have a direct link
Expand All @@ -254,4 +254,4 @@ Summary
-------
``ReportContent`` is made up of many different types of elements (``Sections``, ``Tables``, ``Images``, ``HtmlElements``, ``TimeSeries``), that when
``writeReports()`` is called on the ``ReportContent`` object, have the ability to be rendered through their ``render()`` method in order to be translated
to html for the resulting document. This document is saved in a new folder titled reportsOutputFiles.
to html for the resulting document. This document is saved in a new folder titled reportsOutputFiles.
2 changes: 0 additions & 2 deletions doc/developer/standards_and_practices.rst
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,4 @@ do not use ``super``
``__init__``, use ``ParentClass.__init__(self, plus, additional, arguments)``.

do not leave ``TODO`` statements in production code
NQA-1 requires that the code be "complete", and a ``TODO`` statement leaves the code looking incomplete.
Therefore, do not leave ``TODO`` statements within production code. Instead, open a ticket.
If your ``TODO`` statement is important, perhaps it should be a GitHub Issue.
4 changes: 2 additions & 2 deletions doc/user/accessingEntryPoints.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ There are two ways to access the reports entry point in ARMI.
The first way is through a yaml settings file.
Here, the call is as follows::

(venv) C:\Users\username\codes> tparmi report anl-afci-177.yaml
(venv) $ armi report anl-afci-177.yaml

It is also possible to call this on an h5 file::

(venv) C:\Users\username\codes> tparmi report -h5db refTestBase.h5
(venv) $ armi report -h5db refTestBase.h5

.. note:: When working with a h5 file, -h5db must be included

Expand Down

0 comments on commit 155aeab

Please sign in to comment.