From d451718676c6d815922b121156cf09423e895eb8 Mon Sep 17 00:00:00 2001 From: Josh Meyers Date: Mon, 16 Sep 2024 22:39:14 -0700 Subject: [PATCH 1/4] Modernize testing to pytest --- test_requirements.txt | 3 +- tests/conftest.py | 4 ++ tests/galsim_test_helpers.py | 19 +++--- tests/test_airy.py | 3 +- tests/test_bandpass.py | 3 +- tests/test_bessel.py | 3 +- tests/test_box.py | 12 ++-- tests/test_calc.py | 3 +- tests/test_catalog.py | 3 +- tests/test_cdmodel.py | 3 +- tests/test_celestial.py | 3 +- tests/test_chromatic.py | 15 ++--- tests/test_config_gsobject.py | 3 +- tests/test_config_image.py | 38 +++++++---- tests/test_config_input.py | 3 +- tests/test_config_noise.py | 3 +- tests/test_config_output.py | 3 +- tests/test_config_value.py | 3 +- tests/test_convolve.py | 3 +- tests/test_correlatednoise.py | 20 +++--- tests/test_deltafunction.py | 3 +- tests/test_deprecated.py | 7 +- tests/test_des.py | 7 +- tests/test_detectors.py | 3 +- tests/test_download.py | 3 +- tests/test_draw.py | 3 +- tests/test_errors.py | 3 +- tests/test_exponential.py | 3 +- tests/test_fitsheader.py | 3 +- tests/test_fouriersqrt.py | 3 +- tests/test_galaxy_sample.py | 3 +- tests/test_gaussian.py | 3 +- tests/test_hsm.py | 3 +- tests/test_image.py | 26 +++++--- tests/test_inclined.py | 14 ++-- tests/test_integ.py | 3 +- tests/test_interpolatedimage.py | 80 +++++++++++++---------- tests/test_knots.py | 11 ++-- tests/test_kolmogorov.py | 3 +- tests/test_lensing.py | 3 +- tests/test_main.py | 3 +- tests/test_metacal.py | 3 +- tests/test_moffat.py | 3 +- tests/test_noise.py | 3 +- tests/test_optics.py | 9 +-- tests/test_phase_psf.py | 25 +++---- tests/test_photon_array.py | 7 +- tests/test_pse.py | 3 +- tests/test_random.py | 7 +- tests/test_real.py | 15 ++--- tests/test_roman.py | 28 +++++--- tests/test_second_kick.py | 15 ++--- tests/test_sed.py | 3 +- tests/test_sensor.py | 15 ++--- tests/test_sersic.py | 13 ++-- tests/test_shapelet.py | 3 +- tests/test_shear.py | 3 +- tests/test_shear_position.py | 3 +- tests/test_spergel.py | 3 +- tests/test_sum.py | 3 +- tests/test_table.py | 3 +- tests/test_transforms.py | 10 +-- tests/test_utilities.py | 3 +- tests/test_vonkarman.py | 14 ++-- tests/test_wcs.py | 112 +++++++++++++++++--------------- tests/test_zernike.py | 3 +- 66 files changed, 327 insertions(+), 322 deletions(-) create mode 100644 tests/conftest.py diff --git a/test_requirements.txt b/test_requirements.txt index 0a057c84b8..fc676b1bfd 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -1,7 +1,6 @@ pyyaml>=3.12 -pytest>=3.4, <8 +pytest>=3.4 pytest-xdist>=1.19 pytest-timeout>=1.2 scipy>=1.0 -nose>=1.3 matplotlib diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000000..2ecbe8f384 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,4 @@ +def pytest_addoption(parser): + parser.addoption( + "--run_slow", action="store_true", default=False, help="Run slow tests" + ) diff --git a/tests/galsim_test_helpers.py b/tests/galsim_test_helpers.py index 128075c61e..8d8860ac02 100644 --- a/tests/galsim_test_helpers.py +++ b/tests/galsim_test_helpers.py @@ -16,6 +16,7 @@ # and/or other materials provided with the distribution. # +import pytest import numpy as np import galsim @@ -389,24 +390,26 @@ def drawNoise(noise): return im.array.astype(np.float32).tolist() -def runtests(testfns, parser=None): +# Define a fixture to check if the tests were run via python script +@pytest.fixture +def run_slow(pytestconfig): + return pytestconfig.getoption("--run_slow", default=False) + + +def runtests(filename, parser=None): if parser is None: from argparse import ArgumentParser parser = ArgumentParser() - parser.add_argument('-k', type=str, help='Run only the tests that match the given substring expression.') parser.add_argument('--profile', action='store_true', help='Profile tests') parser.add_argument('--prof_out', default=None, help="Profiler output file") - args = parser.parse_args() + args, unknown_args = parser.parse_known_args() + pytest_args = [filename] + unknown_args + ["--run_slow"] if args.profile: import cProfile, pstats pr = cProfile.Profile() pr.enable() - - for testfn in testfns: - if args.k is None or args.k in testfn.__name__: - testfn() - + pytest.main(pytest_args) if args.profile: pr.disable() ps = pstats.Stats(pr).sort_stats('tottime') diff --git a/tests/test_airy.py b/tests/test_airy.py index dafd35ab1e..4ae8c2c7fb 100644 --- a/tests/test_airy.py +++ b/tests/test_airy.py @@ -280,5 +280,4 @@ def test_ne(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_bandpass.py b/tests/test_bandpass.py index 55f4c08f14..edfcfba87b 100644 --- a/tests/test_bandpass.py +++ b/tests/test_bandpass.py @@ -398,5 +398,4 @@ def test_truncate_inputs(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_bessel.py b/tests/test_bessel.py index 817c2eeaca..f86285c28c 100644 --- a/tests/test_bessel.py +++ b/tests/test_bessel.py @@ -503,5 +503,4 @@ def test_ci(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_box.py b/tests/test_box.py index fa05e9cb7c..4c9b8f0e39 100644 --- a/tests/test_box.py +++ b/tests/test_box.py @@ -27,7 +27,7 @@ # images. @timer -def test_box(): +def test_box(run_slow): """Test the generation of a specific box profile against a known result. """ savedImg = galsim.fits.read(os.path.join(imgdir, "box_1.fits")) @@ -81,7 +81,7 @@ def test_box(): box = galsim.Box(width=width, height=height, flux=test_flux, gsparams=gsp) check_basic(box, "Box with width,height = %f,%f"%(width,height)) do_shoot(box,im,"Box with width,height = %f,%f"%(width,height)) - if __name__ == '__main__': + if run_slow: # These are slow because they require a pretty huge fft. # So only do them if running as main. do_kvalue(box,im,"Box with width,height = %f,%f"%(width,height)) @@ -118,7 +118,7 @@ def test_box(): box = box.shear(galsim.Shear(g1=0.2, g2=-0.3)) check_basic(box, "Sheared Box", approx_maxsb=True) do_shoot(box,im, "Sheared Box") - if __name__ == '__main__': + if run_slow: do_kvalue(box,im, "Sheared Box") check_pickle(box, lambda x: x.drawImage(method='no_pixel')) check_pickle(box) @@ -129,7 +129,7 @@ def test_box(): np.testing.assert_almost_equal(box.xValue(cen), box.max_sb) # This is also a profile that may be convolved using real space convolution, so test that. - if __name__ == '__main__': + if run_slow: conv = galsim.Convolve(box, galsim.Pixel(scale=scale), real_space=True) check_basic(conv, "Sheared Box convolved with pixel in real space", approx_maxsb=True, scale=0.2) @@ -317,6 +317,6 @@ def test_ne(): galsim.TopHat(radius=1.0, gsparams=gsp)] check_all_diff(gals) + if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_calc.py b/tests/test_calc.py index 599050618c..a80e82c71f 100644 --- a/tests/test_calc.py +++ b/tests/test_calc.py @@ -370,5 +370,4 @@ def test_fwhm(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_catalog.py b/tests/test_catalog.py index 11623ec60f..a2520548c5 100644 --- a/tests/test_catalog.py +++ b/tests/test_catalog.py @@ -330,5 +330,4 @@ def test_output_catalog(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_cdmodel.py b/tests/test_cdmodel.py index 24b3dc749d..06cc1aa432 100644 --- a/tests/test_cdmodel.py +++ b/tests/test_cdmodel.py @@ -360,5 +360,4 @@ def test_exampleimage(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_celestial.py b/tests/test_celestial.py index 1a64f37283..193bf93ae2 100644 --- a/tests/test_celestial.py +++ b/tests/test_celestial.py @@ -747,5 +747,4 @@ def test_ecliptic(): if __name__ == '__main__': - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_chromatic.py b/tests/test_chromatic.py index 23afd9de46..63df9f20c8 100644 --- a/tests/test_chromatic.py +++ b/tests/test_chromatic.py @@ -500,7 +500,7 @@ def test_monochromatic_filter(): "GSObject.drawImage()") @timer -def test_monochromatic_sed(): +def test_monochromatic_sed(run_slow): # Similar to the above test, but this time with a broad bandpass and a narrow sed. bandpass = galsim.Bandpass(galsim.LookupTable([500,1000], [1,1], 'linear'), wave_type='nm') @@ -515,7 +515,7 @@ def test_monochromatic_sed(): nstruts = 5 aberrations = np.array([0,0,0,0, 0.02, -0.05, -0.15, -0.02, 0.13, 0.06, -0.09, 0.11]) - if __name__ == '__main__': + if run_slow: wave_list = [515, 690, 900] else: wave_list = [515] @@ -2089,7 +2089,7 @@ def __repr__(self): @timer -def test_ChromaticOpticalPSF(): +def test_ChromaticOpticalPSF(run_slow): """Test the ChromaticOpticalPSF functionality.""" import time @@ -2174,7 +2174,7 @@ def test_ChromaticOpticalPSF(): print("Time to initialize InterpolatedChromaticObject: {0}s".format(t5-t4)) obj = galsim.Convolve(star, psf) - if __name__ == '__main__': + if run_slow: # This is slow, but it is worth testing the pickling of InterpolatedChromaticObjects. check_pickle(psf) else: @@ -2304,7 +2304,7 @@ def test_ChromaticAiry(): err_msg='ChromaticObject flux is wrong when convolved with ChromaticAiry') @timer -def test_phot(): +def test_phot(run_slow): """Test photon shooting with various chromatic PSFs. """ import time @@ -2391,7 +2391,7 @@ def test_phot(): print('fft time = ',t1-t0) print('im1.max,sum = ', im1.array.max(), im1.array.sum()) - if __name__ == '__main__': + if run_slow: # Now the direct photon shooting method t0 = time.time() # This is the old way that photon shooting used to work. The new way will be tested @@ -3388,5 +3388,4 @@ def test_save_photons(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_config_gsobject.py b/tests/test_config_gsobject.py index 99ef076b32..6eba44ee8a 100644 --- a/tests/test_config_gsobject.py +++ b/tests/test_config_gsobject.py @@ -2167,5 +2167,4 @@ def test_sed(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_config_image.py b/tests/test_config_image.py index bf68d51f62..163e57a5a6 100644 --- a/tests/test_config_image.py +++ b/tests/test_config_image.py @@ -28,6 +28,7 @@ import galsim from galsim_test_helpers import * + @timer def test_single(): """Test the default image type = Single and stamp type = Basic @@ -685,6 +686,7 @@ def HighN(config, base, value_type): expected_fluxes = [0, 76673, 0, 0, 24074, 0, 0, 9124, 0, 0, 0] np.testing.assert_almost_equal(fluxes, expected_fluxes, decimal=0) + @timer def test_snr(): """Test signal-to-noise option for setting the flux @@ -1132,6 +1134,7 @@ def test_scattered(): image = galsim.fits.read('output/test_scattered.fits') np.testing.assert_almost_equal(image.array, image2.array) + @timer def test_scattered_noskip(): """The default StampBuilder will automatically skip objects whose stamps are fully @@ -1199,6 +1202,7 @@ def updateSkip(self, prof, image, method, offset, config, base, logger): image2 = galsim.config.BuildImage(config) np.testing.assert_equal(image2.array, image.array) + @timer def test_scattered_whiten(): """Test whitening with the image type Scattered. In particular getting the noise flattened @@ -1970,6 +1974,7 @@ def test_wcs(): builder = galsim.config.wcs.WCSBuilder() assert_raises(NotImplementedError, builder.buildWCS, config, config, logger=None) + @timer def test_bandpass(): """Test various bandpass options""" @@ -2061,7 +2066,7 @@ def test_bandpass(): @timer -def test_index_key(): +def test_index_key(run_slow): """Test some aspects of setting non-default index_key values """ nfiles = 3 @@ -2073,7 +2078,7 @@ def test_index_key(): # First generate using the config layer. config = galsim.config.ReadConfig('config_input/index_key.yaml')[0] - if __name__ == '__main__': + if run_slow: logger = logging.getLogger('test_index_key') logger.addHandler(logging.StreamHandler(sys.stdout)) logger.setLevel(logging.DEBUG) @@ -2089,7 +2094,7 @@ def test_index_key(): logger=logger) images1 = [ galsim.fits.readMulti('output/index_key%02d.fits'%n) for n in range(nfiles) ] - if __name__ == '__main__': + if run_slow: # For nose tests skip these 3 to save some time. # images5 is really the hardest test, and images1 is the easiest, so those two will # give good diagnostics for any errors. @@ -2188,12 +2193,12 @@ def test_index_key(): final = galsim.Convolve(gal, psf) final.drawImage(stamp) - if __name__ == '__main__': + if run_slow: im.write('output/test_index_key%02d_%02d.fits'%(n,i)) images5[n][i].write('output/test_index_key%02d_%02d_5.fits'%(n,i)) np.testing.assert_array_equal(im.array, images1[n][i].array, "index_key parsing failed for sequential BuildFiles run") - if __name__ == '__main__': + if run_slow: np.testing.assert_array_equal(im.array, images2[n][i].array, "index_key parsing failed for output.nproc > 1") np.testing.assert_array_equal(im.array, images3[n][i].array, @@ -2252,7 +2257,7 @@ def test_index_key(): @timer -def test_multirng(): +def test_multirng(run_slow): """Test using multiple rngs. This models a run where the galaxies are the same for 3 images, then a new set for the next @@ -2265,7 +2270,7 @@ def test_multirng(): - Multiple input fields (although tests in test_config_value.py also do this) - Using a non-default build_index for power_spectrum """ - if __name__ == '__main__': + if run_slow: nimages = 6 ngals = 20 logger = logging.getLogger('test_multirng') @@ -2336,7 +2341,7 @@ def test_multirng(): if b.isDefined(): im[b] += stamp[b] im.addNoise(galsim.GaussianNoise(sigma=0.001, rng=rng)) - if __name__ == '__main__': + if run_slow: im.write('output/test_multirng%02d.fits'%n) np.testing.assert_array_equal(im.array, images1[n].array) np.testing.assert_array_equal(im.array, images2[n].array) @@ -2375,7 +2380,7 @@ def test_multirng(): @timer -def test_sequential_seeds(): +def test_sequential_seeds(run_slow): """Test using sequential seeds for successive images. Our old (<=2.3) way of setting rng seeds involved using the nominal seed value for @@ -2395,7 +2400,7 @@ def test_sequential_seeds(): seeds for multiple images is completely fine. This test confirms that. (It fails for the old way of doing the seed sequence.) """ - if __name__ == '__main__': + if run_slow: nimages = 6 ngals = 20 logger = logging.getLogger('test_sequential_seeds') @@ -2424,6 +2429,7 @@ def test_sequential_seeds(): print(i,j,stampi==stampj) assert stampi not in all_stamps[n-1] + @timer def test_template(): """Test various uses of the template keyword @@ -2752,6 +2758,7 @@ def draw(self, profiles, image, method, offset, config, base, logger): return image + @timer def test_blend(): """Test the functionality used by the BlendSet stamp type in examples/des/blend.py. @@ -2824,11 +2831,12 @@ def test_blend(): with assert_raises(galsim.GalSimConfigError): galsim.config.BuildStamp(config, obj_num=8) + @timer -def test_chromatic(): +def test_chromatic(run_slow): """Test drawing a chromatic object on an image with a bandpass """ - if __name__ == '__main__': + if run_slow: bp_file = 'LSST_r.dat' else: # In nosetests, use a simple bandpass to go faster. @@ -3088,6 +3096,7 @@ def test_chromatic(): with assert_raises(galsim.GalSimConfigError): galsim.config.BuildImage(config) + @timer def test_photon_ops(): # Test photon ops in config @@ -3272,6 +3281,7 @@ def test_photon_ops(): with assert_raises(galsim.GalSimConfigError): galsim.config.BuildPhotonOp(config['stamp']['photon_ops'], 0, config) + @timer def test_sensor(): # Test sensor option in config @@ -3444,6 +3454,7 @@ def test_sensor(): with assert_raises(galsim.GalSimConfigError): galsim.config.BuildSensor(config, 'sensor', config) + @timer def test_initial_image(): # This test simulates a time series of a supernova going off near a big galaxy. @@ -3481,5 +3492,4 @@ def test_initial_image(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_config_input.py b/tests/test_config_input.py index 05aeb0d6a6..9f117d5c70 100644 --- a/tests/test_config_input.py +++ b/tests/test_config_input.py @@ -438,5 +438,4 @@ def Dict3Item(config, base, value_type): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_config_noise.py b/tests/test_config_noise.py index c38a0068b3..f105691db2 100644 --- a/tests/test_config_noise.py +++ b/tests/test_config_noise.py @@ -889,5 +889,4 @@ def test_no_noise(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_config_output.py b/tests/test_config_output.py index 4af7c6ec39..99b379110e 100644 --- a/tests/test_config_output.py +++ b/tests/test_config_output.py @@ -1779,5 +1779,4 @@ def test_direct_extra_output(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_config_value.py b/tests/test_config_value.py index e0acbfc56e..a45c34a000 100644 --- a/tests/test_config_value.py +++ b/tests/test_config_value.py @@ -2024,5 +2024,4 @@ def test_astropy_unit(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_convolve.py b/tests/test_convolve.py index 53984c6223..950ac5b137 100644 --- a/tests/test_convolve.py +++ b/tests/test_convolve.py @@ -1002,5 +1002,4 @@ def test_gsparams(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_correlatednoise.py b/tests/test_correlatednoise.py index 6848fc04c4..996d899676 100644 --- a/tests/test_correlatednoise.py +++ b/tests/test_correlatednoise.py @@ -709,6 +709,7 @@ def test_copy(): check_pickle(cn, drawNoise) check_pickle(cn) + @timer def test_add(): """Adding two correlated noise objects, just adds their profiles. @@ -740,6 +741,7 @@ def test_add(): print('diff.variance = ',diff.getVariance()) np.testing.assert_allclose(diff.getVariance(), ccn.getVariance() - ucn2.getVariance()) + @timer def test_cosmos_and_whitening(): """Test that noise generated by an HST COSMOS correlated noise is correct and correctly @@ -853,12 +855,12 @@ def test_cosmos_and_whitening(): @timer -def test_symmetrizing(): +def test_symmetrizing(run_slow): """Test that noise generated by an HST COSMOS correlated noise is correctly symmetrized. Includes test for a magnified, sheared, and rotated version of the COSMOS noise, and tests convolution with a ground-based PSF. """ - if __name__ == "__main__": + if run_slow: # symm_divide determines how close to zero we need to be. Bigger is looser tolerance. symm_divide = 2. symm_size_mult = 6 # make really huge images @@ -976,8 +978,9 @@ def test_symmetrizing(): assert_raises(ValueError, ccn.symmetrizeImage, outimage, order=5) assert_raises(galsim.GalSimUndefinedBoundsError, ccn.symmetrizeImage, galsim.Image()) + @timer -def test_convolve_cosmos(): +def test_convolve_cosmos(run_slow): """Test that a COSMOS noise field convolved with a ground based PSF-style kernel matches the output of the correlated noise model modified with the convolvedWith method. """ @@ -1021,7 +1024,7 @@ def test_convolve_cosmos(): cimobj_padded = galsim.Convolve(imobj_padded, psf_shera) if False: # Switch this for more rigorous tests (takes a long time!) - #if __name__ != "__main__": + #if not run_slow: # The convolve_cosmos test, which includes a lot of the correlated noise functionality is # fairly sensitive at 2dp, but takes ~200s on a mid-range laptop decimal_convolve_cosmos = 2 @@ -1217,8 +1220,9 @@ def test_variance_changes(): assert_raises(galsim.GalSimError, galsim.BaseCorrelatedNoise.from_file, bad_center_file_name, 0.1) + @timer -def test_cosmos_wcs(): +def test_cosmos_wcs(run_slow): """Test how getCOSMOSNoise works when applied to an image with a WCS. """ var = 1.7 @@ -1241,7 +1245,7 @@ def test_cosmos_wcs(): # correctly. I don't think this is a problem, so don't include that in the test list. # This test isn't super fast, so for regular unit tests, just do the last one. - if __name__ != "__main__": + if not run_slow: test_wcs_list = test_wcs_list[-1:] for k, test_wcs in enumerate(test_wcs_list): @@ -1316,6 +1320,7 @@ def test_covariance_spectrum(): check_pickle(covspec) check_pickle(covspec, lambda x: x.toNoise(bp, psf, wcs, rng=bd)) + @timer def test_gsparams(): """Test withGSParams @@ -1353,5 +1358,4 @@ def test_gsparams(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_deltafunction.py b/tests/test_deltafunction.py index e122875c76..56477f6ad1 100644 --- a/tests/test_deltafunction.py +++ b/tests/test_deltafunction.py @@ -206,5 +206,4 @@ def test_deltaFunction_convolution(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_deprecated.py b/tests/test_deprecated.py index 0e562531ab..ea7141914a 100644 --- a/tests/test_deprecated.py +++ b/tests/test_deprecated.py @@ -383,7 +383,7 @@ def test_wfirst(): assert galsim.wfirst.NLfunc is galsim.roman.NLfunc @timer -def test_roman_psfs(): +def test_roman_psfs(run_slow): """Test the deprecated high_accuracy and approximate_struts options. """ import galsim.roman @@ -396,7 +396,7 @@ def test_roman_psfs(): ({ 'approximate_struts':False, 'high_accuracy':False }, { 'pupil_bin':4 }), ] - if __name__ == "__main__": + if run_slow: test_kwargs.append( ({ 'approximate_struts':False, 'high_accuracy':True }, { 'pupil_bin':1, 'gsparams':galsim.GSParams(folding_threshold=2.e-3) }), @@ -970,5 +970,4 @@ def test_save_photons(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_des.py b/tests/test_des.py index c6f6e72404..dc1d92b55b 100644 --- a/tests/test_des.py +++ b/tests/test_des.py @@ -280,12 +280,12 @@ def test_meds(): @timer -def test_meds_config(): +def test_meds_config(run_slow): """ Create a meds file from a config and compare with a manual creation. """ # Some parameters: - if __name__ == '__main__': + if run_slow: nobj = 5 n_per_obj = 8 else: @@ -756,5 +756,4 @@ def test_psf_config(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_detectors.py b/tests/test_detectors.py index f2811721b5..6543c5abc4 100644 --- a/tests/test_detectors.py +++ b/tests/test_detectors.py @@ -512,5 +512,4 @@ def test_Persistence_basic(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_download.py b/tests/test_download.py index 10808ac562..4583f9e58b 100644 --- a/tests/test_download.py +++ b/tests/test_download.py @@ -668,5 +668,4 @@ def test_full(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_draw.py b/tests/test_draw.py index 24e22bca78..48f0f5abe1 100644 --- a/tests/test_draw.py +++ b/tests/test_draw.py @@ -1689,5 +1689,4 @@ def test_direct_scale(): assert_raises(ValueError, obj.makePhot, n_photons=-20) if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_errors.py b/tests/test_errors.py index c655b52ea0..f407857aed 100644 --- a/tests/test_errors.py +++ b/tests/test_errors.py @@ -298,5 +298,4 @@ def test_galsim_deprecation_warning(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_exponential.py b/tests/test_exponential.py index 8d3549d41e..75fde37456 100644 --- a/tests/test_exponential.py +++ b/tests/test_exponential.py @@ -246,5 +246,4 @@ def test_ne(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_fitsheader.py b/tests/test_fitsheader.py index 13f9e08e9c..8153225662 100644 --- a/tests/test_fitsheader.py +++ b/tests/test_fitsheader.py @@ -292,5 +292,4 @@ def test_comments(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_fouriersqrt.py b/tests/test_fouriersqrt.py index ddb16c7919..3dbcce2fd7 100644 --- a/tests/test_fouriersqrt.py +++ b/tests/test_fouriersqrt.py @@ -101,5 +101,4 @@ def test_fourier_sqrt(): assert_raises(NotImplementedError, sqrt1.shoot, 1) if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_galaxy_sample.py b/tests/test_galaxy_sample.py index be3f1904b6..7da83ceaf5 100644 --- a/tests/test_galaxy_sample.py +++ b/tests/test_galaxy_sample.py @@ -399,5 +399,4 @@ def test_cosmos_deep(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_gaussian.py b/tests/test_gaussian.py index a8657618eb..6435a50b63 100644 --- a/tests/test_gaussian.py +++ b/tests/test_gaussian.py @@ -406,5 +406,4 @@ def test_accurate_shift(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_hsm.py b/tests/test_hsm.py index 1d06284ff0..331f5997b0 100644 --- a/tests/test_hsm.py +++ b/tests/test_hsm.py @@ -1035,5 +1035,4 @@ def test_negative_stepstride(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_image.py b/tests/test_image.py index 2d6e1a7b33..48e8be3c7d 100644 --- a/tests/test_image.py +++ b/tests/test_image.py @@ -385,6 +385,7 @@ def test_Image_basic(): check_pickle(galsim.BoundsI(2,3,7,8)) check_pickle(galsim.BoundsD(2.1, 4.3, 6.5, 9.1)) + @timer def test_undefined_image(): """Test various ways to construct an image with undefined bounds @@ -475,8 +476,9 @@ def test_undefined_image(): check_pickle(im1.view()) check_pickle(im1.view(make_const=True)) + @timer -def test_Image_FITS_IO(): +def test_Image_FITS_IO(run_slow): """Test that all six FITS reference images are correctly read in by both PyFITS and our Image wrappers. """ @@ -563,7 +565,7 @@ def test_Image_FITS_IO(): # These tests are a bit slow, so we only bother to run them for the first dtype # when doing the regular unit tests. When running python test_image.py, all of them # will run, so when working on the code, it is a good idea to run the tests that way. - if i > 0 and __name__ != "__main__": + if i > 0 and not run_slow: continue test_file0 = test_file # Save the name of the uncompressed file. @@ -699,8 +701,9 @@ def test_Image_FITS_IO(): im = galsim.fits.read(nowcs_file, suppress_warning=False) assert im.wcs == galsim.PixelScale(1.0) + @timer -def test_Image_MultiFITS_IO(): +def test_Image_MultiFITS_IO(run_slow): """Test that all six FITS reference images are correctly read in by both PyFITS and our Image wrappers. """ @@ -860,7 +863,7 @@ def test_Image_MultiFITS_IO(): # These tests are a bit slow, so we only bother to run them for the first dtype # when doing the regular unit tests. When running python test_image.py, all of them # will run, so when working on the code, it is a good idea to run the tests that way. - if i > 0 and __name__ != "__main__": + if i > 0 and not run_slow: continue test_multi_file0 = test_multi_file @@ -1027,7 +1030,7 @@ def test_Image_MultiFITS_IO(): @timer -def test_Image_CubeFITS_IO(): +def test_Image_CubeFITS_IO(run_slow): """Test that all six FITS reference images are correctly read in by both PyFITS and our Image wrappers. """ @@ -1190,7 +1193,7 @@ def test_Image_CubeFITS_IO(): # These tests are a bit slow, so we only bother to run them for the first dtype # when doing the regular unit tests. When running python test_image.py, all of them # will run, so when working on the code, it is a good idea to run the tests that way. - if i > 0 and __name__ != "__main__": + if i > 0 and not run_slow: continue test_cube_file0 = test_cube_file @@ -1414,6 +1417,7 @@ def test_Image_binary_add(): with assert_raises(ValueError): image1 + image1.subImage(galsim.BoundsI(1,3,1,3)) + @timer def test_Image_binary_subtract(): """Test that all six types of supported Images subtract correctly. @@ -2025,6 +2029,7 @@ def test_Image_inplace_scalar_pow(): with assert_raises(TypeError): image1 **= image2 + @timer def test_Image_subImage(): """Test that subImages are accessed and written correctly. @@ -2128,6 +2133,7 @@ def make_subImage(file_name, bounds): stamp = full_im.subImage(bounds) return stamp + @timer def test_subImage_persistence(): """Test that a subimage is properly accessible even if the original image has gone out @@ -2147,6 +2153,7 @@ def test_subImage_persistence(): np.testing.assert_array_equal(stamp1.array, stamp2.array) + @timer def test_Image_resize(): """Test that the Image resize function works correctly. @@ -2751,6 +2758,7 @@ def test_complex_image(): check_pickle(im3_view) check_pickle(im4_view) + @timer def test_complex_image_arith(): """Additional arithmetic tests that are relevant for complex Image types @@ -2912,6 +2920,7 @@ def test_complex_image_arith(): np.testing.assert_almost_equal(image4.array, (9+13j)/25., decimal=12, err_msg="ImageCD / ImageCD is not correct") + @timer def test_int_image_arith(): """Additional arithmetic tests that are relevant for integer Image types @@ -3416,6 +3425,7 @@ def test_FITS_bad_type(): # Don't forget to set it back to the original. setattr(galsim.Image,'valid_dtypes',orig_dtypes) + @timer def test_bin(): """Test the bin and subsample methods""" @@ -3531,6 +3541,7 @@ def test_bin(): np.testing.assert_almost_equal((origin6.x, origin6.y), (origin1.x, origin1.y), 6, "Binning past the edge resulted in wrong wcs") + @timer def test_fpack(): """Test the functionality that we advertise as being equivalent to fpack/funpack @@ -3639,5 +3650,4 @@ def test_flips(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_inclined.py b/tests/test_inclined.py index 7fcd83e325..98062ecd32 100644 --- a/tests/test_inclined.py +++ b/tests/test_inclined.py @@ -96,6 +96,7 @@ def get_prof(mode, *args, **kwargs): return prof + @timer def test_regression(): """Test that the inclined exponential profile matches the results from Lance Miller's code. @@ -255,6 +256,7 @@ def test_exponential(): check_basic(inc_profile, "Face-on " + mode) + @timer def test_sersic(): """ Test that InclinedSersic looks identical to a Sersic when inclination is zero. @@ -312,6 +314,7 @@ def test_sersic(): check_basic(inc_profile, "Face-on " + mode) + @timer def test_edge_on(): """ Test that an edge-on profile looks similar to an almost-edge-on profile, and doesn't crash. @@ -461,13 +464,12 @@ def run_sanity_checks(mode, flux, inc_angle, scale_radius, scale_height, pos_ang assert(prof1a.flux > prof2.flux) - @timer -def test_k_limits(): +def test_k_limits(run_slow): """ Check that the maxk and stepk give reasonable results for all profiles. """ test_params = inclined_sersic_regression_test_parameters - if __name__ == '__main__': + if run_slow: test_params += inclined_exponential_test_parameters test_params += inclined_sersic_test_parameters @@ -525,6 +527,7 @@ def test_k_limits(): total_flux = np.sum(test_image.array) assert (total_flux-contained_flux)/total_flux <= gsparams.folding_threshold + @timer def test_eq_ne(): """ Check that equality/inequality works as expected.""" @@ -578,6 +581,7 @@ def test_eq_ne(): check_all_diff(diff_gals) + @timer def test_pickle(): """ Check that we can pickle it. """ @@ -600,6 +604,7 @@ def test_pickle(): scale_height=0.3, flux=10.0, gsparams=galsim.GSParams(folding_threshold=1.1e-3))) + @timer def test_exceptions(): """ Tests to make sure that proper exceptions are thrown when expected. """ @@ -667,5 +672,4 @@ def test_value_retrieval(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_integ.py b/tests/test_integ.py index 537b5c72b1..d82a35eedc 100644 --- a/tests/test_integ.py +++ b/tests/test_integ.py @@ -348,5 +348,4 @@ def test_gq_annulus(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_interpolatedimage.py b/tests/test_interpolatedimage.py index 281b3de568..dd72937efa 100644 --- a/tests/test_interpolatedimage.py +++ b/tests/test_interpolatedimage.py @@ -32,11 +32,10 @@ KXVALS = np.array((1.30, 0.71, -4.30)) * np.pi / 2. KYVALS = np.array((0.80, -0.02, -0.31,)) * np.pi / 2. -def setup(): - # This reference image will be used in a number of tests below, so make it at the start. - global final - global ref_image +@pytest.fixture +def ref(): + # This reference image will be used in a number of tests below, so make it at the start. g1 = galsim.Gaussian(sigma = 3.1, flux=2.4).shear(g1=0.2,g2=0.1) g2 = galsim.Gaussian(sigma = 1.9, flux=3.1).shear(g1=-0.4,g2=0.3).shift(-0.3,0.5) g3 = galsim.Gaussian(sigma = 4.1, flux=1.6).shear(g1=0.1,g2=-0.1).shift(0.7,-0.2) @@ -45,11 +44,14 @@ def setup(): scale = 0.4 # The reference image was drawn with the old convention, which is now use_true_center=False final.drawImage(image=ref_image, scale=scale, method='sb', use_true_center=False) + return final, ref_image + @timer -def test_roundtrip(): +def test_roundtrip(ref): """Test round trip from Image to InterpolatedImage back to Image. """ + final, ref_image = ref # for each type, try to make an InterpolatedImage, and check that when we draw an image from # that InterpolatedImage that it is the same as the original ftypes = [np.float32, np.float64] @@ -382,6 +384,7 @@ def test_interpolant(): with assert_raises(galsim.GalSimValueError): q.kval(x2d) + @timer def test_unit_integrals(): # Test Interpolant.unit_integrals @@ -548,7 +551,7 @@ def test_exceptions(): @timer -def test_operations_simple(): +def test_operations_simple(run_slow): """Simple test of operations on InterpolatedImage: shear, magnification, rotation, shifting.""" # Make some nontrivial image that can be described in terms of sums and convolutions of # GSObjects. We want this to be somewhat hard to describe, but should be at least @@ -625,8 +628,8 @@ def test_operations_simple(): np.testing.assert_allclose(big_im_sub.array, ref_im_sub.array, rtol=0.01) # The check_pickle tests should all pass below, but the a == eval(repr(a)) check can take a - # really long time, so we only do that if __name__ == "__main__". - irreprable = not __name__ == "__main__" + # really long time, so we only do that if run_slow is True. + irreprable = not run_slow check_pickle(test_int_im, lambda x: x.drawImage(nx=5, ny=5, scale=0.1, method='no_pixel'), irreprable=irreprable) check_pickle(test_int_im, irreprable=irreprable) @@ -734,6 +737,7 @@ def test_operations_simple(): irreprable=irreprable) check_pickle(test_int_im, irreprable=irreprable) + @timer def test_operations(): """Test of operations on complicated InterpolatedImage: shear, magnification, rotation, @@ -792,7 +796,7 @@ def test_operations(): @timer -def test_uncorr_padding(): +def test_uncorr_padding(run_slow): """Test for uncorrelated noise padding of InterpolatedImage.""" # Set up some defaults: use weird image sizes / shapes and noise variances. decimal_precise=5 @@ -823,7 +827,7 @@ def test_uncorr_padding(): np.testing.assert_almost_equal( np.var(big_img.array), big_var_expected, decimal=decimal_precise, err_msg='Variance not diluted by expected amount when zero-padding') - if __name__ == '__main__': + if run_slow: check_pickle(int_im, lambda x: x.drawImage(nx=200, ny=200, scale=1, method='no_pixel')) check_pickle(int_im) @@ -840,7 +844,7 @@ def test_uncorr_padding(): np.testing.assert_almost_equal( np.var(big_img.array), noise_var, decimal=decimal_coarse, err_msg='Variance not correct after padding image with noise') - if __name__ == '__main__': + if run_slow: check_pickle(int_im, lambda x: x.drawImage(nx=200, ny=200, scale=1, method='no_pixel')) check_pickle(int_im) else: @@ -863,7 +867,7 @@ def test_uncorr_padding(): np.testing.assert_array_almost_equal( big_img_2.array, big_img.array, decimal=decimal_precise, err_msg='Cannot reproduce noise-padded image with same choice of seed') - if __name__ == '__main__': + if run_slow: check_pickle(int_im, lambda x: x.drawImage(nx=200, ny=200, scale=1, method='no_pixel')) check_pickle(int_im) @@ -873,7 +877,7 @@ def test_uncorr_padding(): @timer -def test_pad_image(): +def test_pad_image(run_slow): """Test padding an InterpolatedImage with a pad_image.""" decimal=2 # all are coarse, since there are slight changes from odd/even centering issues. noise_sigma = 1.73 @@ -925,7 +929,7 @@ def test_pad_image(): np.testing.assert_almost_equal( np.mean(big_img.array**2), var_expected, decimal=decimal, err_msg='Variance not correct when padding with image') - if __name__ == '__main__': + if run_slow: check_pickle(int_im, lambda x: x.drawImage(nx=200, ny=200, scale=1, method='no_pixel')) check_pickle(int_im) @@ -941,13 +945,13 @@ def test_pad_image(): np.testing.assert_almost_equal( np.mean(big_img.array**2), var_expected, decimal=decimal, err_msg='Variance not correct after padding with image and extra noise') - if __name__ == '__main__': + if run_slow: check_pickle(int_im, lambda x: x.drawImage(nx=200, ny=200, scale=1, method='no_pixel')) check_pickle(int_im) @timer -def test_corr_padding(): +def test_corr_padding(run_slow): """Test for correlated noise padding of InterpolatedImage.""" # Set up some defaults for tests. decimal_precise=4 @@ -978,7 +982,7 @@ def test_corr_padding(): big_var_expected = np.var(orig_img.array)*float(orig_nx*orig_ny)/(big_nx*big_ny) np.testing.assert_almost_equal(np.var(big_img.array), big_var_expected, decimal=decimal_precise, err_msg='Variance not diluted by expected amount when zero-padding') - if __name__ == '__main__': + if run_slow: check_pickle(int_im, lambda x: x.drawImage(nx=200, ny=200, scale=1, method='no_pixel')) check_pickle(int_im) @@ -994,7 +998,7 @@ def test_corr_padding(): np.testing.assert_almost_equal(np.var(big_img.array), np.var(orig_img.array), decimal=decimal_coarse, err_msg='Variance not correct after padding image with correlated noise') - if __name__ == '__main__': + if run_slow: check_pickle(int_im, lambda x: x.drawImage(nx=200, ny=200, scale=1, method='no_pixel')) check_pickle(int_im) @@ -1032,7 +1036,7 @@ def test_corr_padding(): np.testing.assert_almost_equal(np.var(big_img.array), np.var(orig_img.array), decimal=decimal_coarse, err_msg='Variance not correct after padding image with correlated noise') - if __name__ == '__main__': + if run_slow: check_pickle(int_im, lambda x: x.drawImage(nx=200, ny=200, scale=1, method='no_pixel')) check_pickle(int_im) @@ -1045,7 +1049,7 @@ def test_corr_padding(): int_im.drawImage(big_img_2, scale=1., method='no_pixel') np.testing.assert_array_almost_equal(big_img_2.array, big_img.array, decimal=decimal_precise, err_msg='Cannot reproduce correlated noise-padded image with same choice of seed') - if __name__ == '__main__': + if run_slow: check_pickle(int_im, lambda x: x.drawImage(nx=200, ny=200, scale=1, method='no_pixel')) check_pickle(int_im) @@ -1069,7 +1073,7 @@ def test_corr_padding(): int_im3.drawImage(big_img3, scale=1., method='no_pixel') np.testing.assert_equal(big_img2.array, big_img3.array, err_msg='Diff ways of specifying correlated noise give diff answers') - if __name__ == '__main__': + if run_slow: check_pickle(int_im2, lambda x: x.drawImage(nx=200, ny=200, scale=1, method='no_pixel')) check_pickle(int_im3, lambda x: x.drawImage(nx=200, ny=200, scale=1, method='no_pixel')) check_pickle(int_im2) @@ -1077,7 +1081,7 @@ def test_corr_padding(): @timer -def test_realspace_conv(): +def test_realspace_conv(run_slow): """Test that real-space convolution of an InterpolatedImage matches the FFT result """ # Note: It is not usually a good idea to use real-space convolution with an InterpolatedImage. @@ -1101,7 +1105,7 @@ def test_realspace_conv(): psf1 = galsim.Gaussian(flux=1, half_light_radius=0.77) psf_im = psf1.drawImage(scale=raw_scale, nx=raw_size, ny=raw_size, method='no_pixel') - if __name__ == "__main__": + if run_slow: interp_list = ['linear', 'cubic', 'quintic', 'lanczos3', 'lanczos5', 'lanczos7'] else: interp_list = ['linear', 'cubic', 'quintic'] @@ -1151,9 +1155,10 @@ def test_realspace_conv(): @timer -def test_Cubic_ref(): +def test_Cubic_ref(ref): """Test use of Cubic interpolant against some reference values """ + final, ref_image = ref interp = galsim.Cubic() scale = 0.4 testobj = galsim.InterpolatedImage(ref_image, x_interpolant=interp, scale=scale, @@ -1177,9 +1182,10 @@ def test_Cubic_ref(): @timer -def test_Quintic_ref(): +def test_Quintic_ref(ref): """Test use of Quintic interpolant against some reference values """ + final, ref_image = ref interp = galsim.Quintic() scale = 0.4 testobj = galsim.InterpolatedImage(ref_image, x_interpolant=interp, scale=scale, @@ -1202,9 +1208,10 @@ def test_Quintic_ref(): @timer -def test_Lanczos5_ref(): +def test_Lanczos5_ref(ref): """Test use of Lanczos5 interpolant against some reference values """ + final, ref_image = ref interp = galsim.Lanczos(5, conserve_dc=False) scale = 0.4 testobj = galsim.InterpolatedImage(ref_image, x_interpolant=interp, scale=scale, @@ -1227,9 +1234,10 @@ def test_Lanczos5_ref(): @timer -def test_Lanczos7_ref(): +def test_Lanczos7_ref(ref): """Test use of Lanczos7 interpolant against some reference values """ + final, ref_image = ref interp = galsim.Lanczos(7, conserve_dc=False) scale = 0.4 testobj = galsim.InterpolatedImage(ref_image, x_interpolant=interp, scale=scale, @@ -1394,9 +1402,10 @@ def test_stepk_maxk(): @timer -def test_kroundtrip(): +def test_kroundtrip(ref): """ Test that GSObjects `a` and `b` are the same when b = InterpolatedKImage(a.drawKImage) """ + final, ref_image = ref a = final kim_a = a.drawKImage() b = galsim.InterpolatedKImage(kim_a) @@ -1569,7 +1578,7 @@ def test_multihdu_readin(): @timer -def test_ii_shoot(): +def test_ii_shoot(run_slow): """Test InterpolatedImage with photon shooting. Particularly the flux of the final image. """ rng = galsim.BaseDeviate(1234) @@ -1583,7 +1592,7 @@ def test_ii_shoot(): 'lanczos3', 'lanczos5', 'lanczos7'] im = galsim.Image(100,100, scale=1) im.setCenter(0,0) - if __name__ == '__main__': + if run_slow: flux = 1.e6 else: flux = 1.e4 @@ -1621,10 +1630,11 @@ def test_ii_shoot(): @timer -def test_ne(): +def test_ne(ref): """ Check that inequality works as expected for corner cases where the reprs of two unequal InterpolatedImages or InterpolatedKImages may be the same due to truncation. """ + final, ref_image = ref obj1 = galsim.InterpolatedImage(ref_image, flux=20, calculate_maxk=False, calculate_stepk=False) # Copy ref_image and perturb it slightly in the middle, away from where the InterpolatedImage @@ -1691,6 +1701,7 @@ def test_ne(): galsim.InterpolatedKImage(kim, gsparams=gsp)] check_all_diff(gals) + @timer def test_quintic_glagn(): """This is code that was giving a seg fault. cf. Issue 1079. @@ -1710,6 +1721,7 @@ def test_quintic_glagn(): gsobj.drawImage(method='phot', image=image, add_to_image=True) + @timer def test_depixelize(): # True, non-II profile. Something not too symmetric or simple. @@ -1841,6 +1853,7 @@ def test_depixelize(): np.testing.assert_allclose(im6.array, im1.array, atol=1.e-2) print(interp,' max error = ',np.max(np.abs(im6.array-im1.array)),' time = ',t2-t1) + @timer def test_drawreal_seg_fault(): """Test to reproduce bug report in Issue #1164 that was causing seg faults @@ -1874,8 +1887,5 @@ def test_drawreal_seg_fault(): np.testing.assert_array_equal(image.array, 0) - if __name__ == "__main__": - setup() - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_knots.py b/tests/test_knots.py index 164f9d1551..eab7837e53 100644 --- a/tests/test_knots.py +++ b/tests/test_knots.py @@ -356,7 +356,7 @@ def test_knots_hlr(): assert abs(mn-hlr) < nstd*std_check, mess @timer -def test_knots_transform(): +def test_knots_transform(run_slow): """Test that overridden transformations give equivalent results as the normal methods. """ def test_op(rw, op): @@ -373,7 +373,7 @@ def test_op(rw, op): np.testing.assert_almost_equal(im1.array, im2.array, decimal=3, err_msg='RandomKnots with op '+op) - if __name__ == '__main__': + if run_slow: npoints = 20 else: npoints = 3 # Not too many, so this test doesn't take forever. @@ -383,7 +383,7 @@ def test_op(rw, op): rw = galsim.RandomKnots(npoints, profile=galsim.Exponential(half_light_radius=hlr, flux=flux), rng=rng) - if __name__ == '__main__': + if run_slow: # First relatively trivial tests of no ops test_op(rw, 'withScaledFlux(1.0)') test_op(rw, 'expand(1.0)') @@ -406,7 +406,7 @@ def test_op(rw, op): test_op(rw, 'shift(0.3, 0.9)') test_op(rw, '_shift(-0.3, 0.2)') - if __name__ == '__main__': + if run_slow: # A couple more that are currently not overridden, but call out to the above functions. test_op(rw, 'magnify(1.2)') test_op(rw, 'lens(0.03, 0.07, 1.12)') @@ -435,5 +435,4 @@ def test_knots_sed(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_kolmogorov.py b/tests/test_kolmogorov.py index a1c47a89b0..c535fe9cb3 100644 --- a/tests/test_kolmogorov.py +++ b/tests/test_kolmogorov.py @@ -402,5 +402,4 @@ def test_low_folding_threshold(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_lensing.py b/tests/test_lensing.py index 04c9ea0025..29a771dbf2 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -1513,5 +1513,4 @@ def test_constant(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_main.py b/tests/test_main.py index c1f8411b7f..302321495e 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -319,5 +319,4 @@ def test_process(): assert os.path.exists(file_name) if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_metacal.py b/tests/test_metacal.py index 9fcd96f1ba..7fba7847a6 100644 --- a/tests/test_metacal.py +++ b/tests/test_metacal.py @@ -418,5 +418,4 @@ def test_wcs(): np.testing.assert_almost_equal(new_im.array.sum()/237, obs_im.array.sum()/237, decimal=1) if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_moffat.py b/tests/test_moffat.py index e98bf1bcbf..f377166736 100644 --- a/tests/test_moffat.py +++ b/tests/test_moffat.py @@ -520,5 +520,4 @@ def test_ne(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_noise.py b/tests/test_noise.py index df788ca004..a7cc0ade61 100644 --- a/tests/test_noise.py +++ b/tests/test_noise.py @@ -840,5 +840,4 @@ def test_addnoisesnr(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_optics.py b/tests/test_optics.py index 6c2398c757..c719e51348 100644 --- a/tests/test_optics.py +++ b/tests/test_optics.py @@ -44,8 +44,6 @@ do_slow_tests = False # do_slow_tests = True # uncomment out for more rigorous testing # Warning: some of them require a LOT of memory. -# if __name__ == "__main__": -# do_slow_tests = True if do_slow_tests: pp_decimal = 5 @@ -69,7 +67,7 @@ @timer -def test_OpticalPSF_flux(): +def test_OpticalPSF_flux(run_slow): """Compare an unaberrated OpticalPSF flux to unity. """ lods = (1.e-8, 4., 9.e5) # lambda/D values: don't choose unity in case symmetry hides something @@ -81,7 +79,7 @@ def test_OpticalPSF_flux(): np.testing.assert_almost_equal(optics_array.sum(), 1., 2, err_msg="Unaberrated Optical flux not quite unity.") - if __name__ == '__main__': + if run_slow: optics_test = galsim.OpticalPSF(lam_over_diam=lod, flux=177) optics_im = optics_test.drawImage(scale=.25*lod, image=image, method='no_pixel') np.testing.assert_almost_equal(optics_im.array.sum(), 177., 2) @@ -929,5 +927,4 @@ def test_geometric_shoot(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_phase_psf.py b/tests/test_phase_psf.py index e2fdf247b1..6d71bb34f4 100644 --- a/tests/test_phase_psf.py +++ b/tests/test_phase_psf.py @@ -112,10 +112,10 @@ def test_atm_screen_size(): @timer -def test_structure_function(): +def test_structure_function(run_slow): """Test that AtmosphericScreen generates the right structure function. """ - if __name__ == '__main__': + if run_slow: L0s = [10.0, 25.0, 100.0] screen_size = 300.0 else: @@ -687,7 +687,7 @@ def test_ne(): @timer -def test_phase_gradient_shoot(): +def test_phase_gradient_shoot(run_slow): """Test that photon-shooting PSFs match Fourier optics PSFs when using the same phase screens, and also match the expected size from an analytic VonKarman-convolved-with-Airy PSF. """ @@ -700,14 +700,14 @@ def test_phase_gradient_shoot(): # Ideally, we'd use as small a screen scale as possible here. The runtime for generating # phase screens scales like `screen_scale`^-2 though, which is pretty steep, so we use a larger- - # than-desireable scale for the __name__ != '__main__' branch. This is known to lead to a bias + # than-desireable scale for the not run_slow branch. This is known to lead to a bias # in PSF size, which we attempt to account for below when actually comparing FFT PSF moments to # photon-shooting PSF moments. Note that we don't need to apply such a correction when # comparing the photon-shooting PSF to the analytic VonKarman PSF since these both avoid the # screen_scale problem to begin with. (Even though we do generate screens for the # photon-shooting PSF, because we truncate the power spectrum above kcrit, we don't require as # high of resolution). - if __name__ == '__main__': + if run_slow: screen_scale = 0.025 # m else: screen_scale = 0.1 # m @@ -760,7 +760,7 @@ def test_phase_gradient_shoot(): u.generate(ys) thetas = [(x*galsim.degrees, y*galsim.degrees) for x, y in zip(xs, ys)] - if __name__ == '__main__': + if run_slow: exptime = 15.0 time_step = 0.05 centroid_tolerance = 0.08 @@ -1192,7 +1192,7 @@ def dummyWork(i, atm): @timer -def test_shared_memory(): +def test_shared_memory(run_slow): """Test that shared memory hooks to AtmosphericScreen work. """ import multiprocessing as mp @@ -1223,7 +1223,7 @@ def test_shared_memory(): dirn.append(u()*360*galsim.degrees) r0_500s.append(r0_500*weights[i]**(-3./5)) - if __name__ == "__main__": + if run_slow: ctxs = [None, mp.get_context("fork"), mp.get_context("spawn"), "forkserver"] else: ctxs = [None, mp.get_context("fork")] @@ -1489,9 +1489,9 @@ def test_user_screen(): @timer -def test_uv_persistence(): +def test_uv_persistence(run_slow): from scipy.spatial.distance import cdist - if __name__ == '__main__': + if run_slow: nphot = 1000000 else: nphot = 1000 @@ -1535,6 +1535,7 @@ def test_t_persistence(): assert np.min(photons.time) > 10.0 assert np.max(photons.time) < 25.0 + @timer def test_convolve_phasepsf(): # This snippet didn't use to be allowed, since the two psfs populate different @@ -1552,6 +1553,6 @@ def test_convolve_phasepsf(): # The main thing is that it works. But check that flux makes sense. assert im.array.sum() == 10 + if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_photon_array.py b/tests/test_photon_array.py index 316f1d51d7..2725440cb0 100644 --- a/tests/test_photon_array.py +++ b/tests/test_photon_array.py @@ -1755,10 +1755,5 @@ def test_scale_wavelength(): check_pickle(scale_wave) - if __name__ == '__main__': - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - if no_astroplan: - print('Skipping test_dcr_angles, since astroplan not installed.') - testfns.remove(test_dcr_angles) - runtests(testfns) + runtests(__file__) diff --git a/tests/test_pse.py b/tests/test_pse.py index f86d5318ba..f5247e81d9 100644 --- a/tests/test_pse.py +++ b/tests/test_pse.py @@ -186,5 +186,4 @@ def test_PSE_weight(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_random.py b/tests/test_random.py index 429137600b..85add0768d 100644 --- a/tests/test_random.py +++ b/tests/test_random.py @@ -838,7 +838,7 @@ def test_poisson(): @timer -def test_poisson_highmean(): +def test_poisson_highmean(run_slow): """Test Poisson random number generator with high (>2^30) mean (cf. Issue #881) It turns out that the boost poisson deviate class that we use maxes out at 2^31 and wraps @@ -853,7 +853,7 @@ def test_poisson_highmean(): 5.e20, # Definitely would have problems with normal implementation. ] - if __name__ == '__main__': + if run_slow: nvals = 10000000 rtol_var = 1.e-3 else: @@ -2024,5 +2024,4 @@ def test_numpy_generator(): assert np.isclose(np.std(a3), 23, rtol=3.e-3) if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_real.py b/tests/test_real.py index eef6312b92..70631051f0 100644 --- a/tests/test_real.py +++ b/tests/test_real.py @@ -367,14 +367,14 @@ def test_pickle_crg(): @timer -def test_crg_roundtrip(): +def test_crg_roundtrip(run_slow): """Test that drawing a ChromaticRealGalaxy using the HST collecting area and filter gives back the original image. """ f606w_cat = galsim.RealGalaxyCatalog('AEGIS_F606w_catalog.fits', dir=image_dir) f814w_cat = galsim.RealGalaxyCatalog('AEGIS_F814w_catalog.fits', dir=image_dir) - indices = [0] if __name__ != "__main__" else list(range(len(f606w_cat))) + indices = [0] if not run_slow else list(range(len(f606w_cat))) for index in indices: orig_f606w = f606w_cat.getGalImage(index) @@ -568,7 +568,7 @@ def test_crg_roundtrip_larger_target_psf(): @timer -def test_ne(): +def test_ne(run_slow): """ Check that inequality works as expected.""" rgc = galsim.RealGalaxyCatalog(catalog_file, dir=image_dir) f606w_cat = galsim.RealGalaxyCatalog('AEGIS_F606w_catalog.fits', dir=image_dir) @@ -603,7 +603,7 @@ def test_ne(): # CovarianceSpectrum and ChromaticRealGalaxy are both reprable, but their reprs are rather # large, so the eval(repr) checks take a long time. # Therefore, run them from command line, but not from pytest. - if __name__ == '__main__': + if run_slow: check_pickle(crg1) check_pickle(covspec1) else: @@ -903,11 +903,11 @@ def check_crg_noise(n_sed, n_im, n_trial, tol): @timer -def test_crg_noise(): +def test_crg_noise(run_slow): """Verify that we can propagate the noise covariance by actually measuring the covariance of some pure noise fields put through ChromaticRealGalaxy. """ - if __name__ == '__main__': + if run_slow: check_crg_noise(2, 2, 50, tol=0.03) check_crg_noise(2, 3, 25, tol=0.03) check_crg_noise(3, 3, 25, tol=0.03) @@ -976,5 +976,4 @@ def test_sys_share_dir(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_roman.py b/tests/test_roman.py index 11968533ce..115fb4d09a 100644 --- a/tests/test_roman.py +++ b/tests/test_roman.py @@ -27,6 +27,7 @@ import galsim.roman from galsim_test_helpers import * + @timer def skip_roman_wcs(): """Test the Roman WCS routines against ones provided by the Roman project office. @@ -136,8 +137,9 @@ def skip_roman_wcs(): np.ones(len(ra_test))*0.0001, err_msg='For at least one WCS, pixel areas differ from reference by >0.01%.') + @timer -def test_roman_wcs(): +def test_roman_wcs(run_slow): """Test the Roman WCS routines against the one produced by code from Chris Hirata. """ # The standard against which we will compare is the output of some software provided by Chris @@ -157,7 +159,7 @@ def test_roman_wcs(): dec = test_data[3,:] pa = test_data[4,:] chris_sca = test_data[5,:] - if __name__ != "__main__": + if not run_slow: i_start = 4 n_test = 3 # None of these 3 fail, so the nfail test is ok. else: @@ -316,6 +318,7 @@ def test_roman_wcs(): with assert_raises(OSError): galsim.roman.getWCS(world_pos=world_pos, date=date) + @timer def test_roman_backgrounds(): """Test the Roman background estimation routines for basic sanity. @@ -488,6 +491,7 @@ def test_roman_bandpass(): for key in nozp_bp: assert nozp_bp[key].zeropoint is None + @timer def test_roman_nonimaging_bandpass(): """Test the Roman non-imaging bandpasses for basic sanity. @@ -509,6 +513,7 @@ def test_roman_nonimaging_bandpass(): assert 'Grism_1stOrder' not in bp_imaging assert 'SNPrism' not in bp_imaging + @timer def test_roman_detectors(): """Test the Roman detector routines for consistency with standard detector routines. @@ -628,7 +633,7 @@ def test_roman_detectors(): @timer -def test_roman_psfs(): +def test_roman_psfs(run_slow): """Test the Roman PSF routines for reasonable behavior. """ # The Roman PSF routines can take a long time under some circumstances. For example, storing @@ -742,7 +747,7 @@ def test_roman_psfs(): { 'pupil_bin':4 }, { 'pupil_bin':8 }, ] - if __name__ == '__main__': + if run_slow: # A few more that are too slow to run in regular nosetests kwargs_list.extend([ { 'pupil_bin':1 }, @@ -781,6 +786,7 @@ def test_roman_psfs(): assert_raises(ValueError, galsim.roman.getPSF, 0, None) assert_raises(ValueError, galsim.roman.getPSF, 3, 'short', n_waves=10) + @timer def test_roman_basic_numbers(): """Trivial test of basic numbers stored in Roman module. @@ -853,6 +859,7 @@ def test_roman_basic_numbers(): assert galsim.roman.jitter_rms==ref_jitter_rms assert galsim.roman.charge_diffusion==ref_charge_diffusion + @timer def test_roman_psf_wcs(): """Test drawing the PSF with a provided WCS.""" @@ -949,6 +956,7 @@ def test_config_psf(): print('psf2 = ',str(psf2)) assert psf1 == psf2 + @timer def test_config_sca(): """Test RomanSCA config type""" @@ -1091,8 +1099,9 @@ def test_config_sca(): im2 -= sky_image assert im1 == im2 + @timer -def test_aberration_interpolation(): +def test_aberration_interpolation(run_slow): """Test the Roman aberration interpolation method inside roman.roman_psfs """ # We read in pairs of conjunction points, they are on different SCAs but are physically @@ -1159,7 +1168,7 @@ def test_aberration_interpolation(): Z_max = np.max(aberration_array, axis=0) Z_range = Z_max - Z_min - if __name__ == '__main__': + if run_slow: from matplotlib import pyplot as plt world_pos = galsim.CelestialCoord(0.*galsim.degrees, 0*galsim.degrees) @@ -1235,7 +1244,7 @@ def test_aberration_interpolation(): @timer -def test_roman_focal_plane(): +def test_roman_focal_plane(run_slow): """Test that a full focal plane has everything oriented as shown in mapping_v210503.pdf """ # For this test, we mostly try to plot points on each SCA that visually reproduce @@ -1391,7 +1400,7 @@ def test_roman_focal_plane(): coords = [wcs[sca].toWorld(galsim.PositionD(x,y)) for x,y in numbers[sca]] numbers[sca] = [(c.ra.deg, c.dec.deg) for c in coords] - if __name__ == '__main__': + if run_slow: from matplotlib.figure import Figure from matplotlib.backends.backend_agg import FigureCanvasAgg @@ -1438,5 +1447,4 @@ def test_roman_focal_plane(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_second_kick.py b/tests/test_second_kick.py index ab6a4a6b94..7d22549ef0 100644 --- a/tests/test_second_kick.py +++ b/tests/test_second_kick.py @@ -24,12 +24,12 @@ @timer -def test_init(): +def test_init(run_slow): """Test generation of SecondKick profiles """ obscuration = 0.5 - if __name__ == '__main__': + if run_slow: lams = [300.0, 500.0, 1100.0] r0_500s = [0.1, 0.15, 0.3] kcrits = [0.1, 0.2, 0.4] @@ -157,7 +157,7 @@ def test_limiting_cases(): atol=1e-4) @timer -def test_sk_phase_psf(): +def test_sk_phase_psf(run_slow): """Test that analytic second kick profile matches what can be obtained from PhaseScreenPSF with an appropriate truncated power spectrum. """ @@ -173,7 +173,7 @@ def test_sk_phase_psf(): speed = [rng()*20 for _ in range(6)] direction = [rng()*360*galsim.degrees for _ in range(6)] aper = galsim.Aperture(4.0, obscuration=obscuration, pad_factor=0.5) - kcrits = [1, 3, 10] if __name__ == '__main__' else [1] + kcrits = [1, 3, 10] if run_slow else [1] for kcrit in kcrits: # Technically, we should probably use a smaller screen_scale here, but that runs really # slowly. The below seems to work well enough for the tested kcrits. @@ -209,7 +209,7 @@ def test_sk_phase_psf(): @timer -def test_sk_scale(): +def test_sk_scale(run_slow): """Test sk scale argument""" kwargs = {'lam':500, 'r0':0.2, 'diam':4.0, 'flux':2.2, 'obscuration':0.3} sk_arcsec = galsim.SecondKick(scale_unit=galsim.arcsec, **kwargs) @@ -234,7 +234,7 @@ def test_sk_scale(): sk_arcmin._sba.xValue(galsim.PositionD(0.0, 0.01)._p)/60**2, decimal=5) - if __name__ == '__main__': + if run_slow: # These are a little slow, since the xValue is doing a real-space convolution integral. np.testing.assert_almost_equal(sk_arcsec.xValue(0.0, 6.0), sk_arcmin.xValue(0.0, 0.1)/60**2, @@ -301,5 +301,4 @@ def test_sk_ne(): if __name__ == '__main__': - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_sed.py b/tests/test_sed.py index dcb262d74a..02c3973a76 100644 --- a/tests/test_sed.py +++ b/tests/test_sed.py @@ -1274,5 +1274,4 @@ def test_flux_type_calculateFlux(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 7077ee28fa..d8468fc65f 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -561,7 +561,7 @@ def test_silicon_area(): @timer -def test_sensor_wavelengths_and_angles(): +def test_sensor_wavelengths_and_angles(run_slow): print('Starting test_wavelengths_and_angles') sys.stdout.flush() @@ -577,7 +577,7 @@ def test_sensor_wavelengths_and_angles(): assigner = galsim.FRatioAngles(fratio, obscuration) obj = galsim.Gaussian(flux=3539, sigma=0.3) - if __name__ == "__main__": + if run_slow: bands = ['r', 'i', 'z', 'y'] else: bands = ['i'] # Only test the i band for pytest @@ -914,14 +914,14 @@ def test_treerings(): @timer -def test_resume(): +def test_resume(run_slow): """Test that the resume option for accumulate works properly. """ # Note: This test is based on a script devel/lsst/treering_skybg_check.py rng = galsim.UniformDeviate(314159) - if __name__ == "__main__": + if run_slow: flux_per_pixel = 40 nx = 200 ny = 200 @@ -1024,12 +1024,12 @@ def test_resume(): assert_raises(RuntimeError, sensor4.accumulate, all_photons, im1, resume=True) @timer -def test_flat(): +def test_flat(run_slow): """Test building a flat field image using the Silicon class. """ # Note: This test is based on a script devel/lsst/treering_flat.py - if __name__ == '__main__': + if run_slow: nx = 200 ny = 200 nflats = 20 @@ -1277,5 +1277,4 @@ def test_big_then_small(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_sersic.py b/tests/test_sersic.py index 971cdf3af6..3ec7d50830 100644 --- a/tests/test_sersic.py +++ b/tests/test_sersic.py @@ -16,6 +16,7 @@ # and/or other materials provided with the distribution. # +import pytest import numpy as np import os @@ -165,13 +166,13 @@ def test_sersic(): @timer -def test_sersic_radii(): +def test_sersic_radii(run_slow): """Test initialization of Sersic with different types of radius specification. """ import math test_hlr = 1.8 - if __name__ != "__main__": + if not run_slow: # If doing a pytest run, we don't actually need to do all 4 sersic n values. # Two should be enough to notice if there is a problem, and the full list will be tested # when running python test_sersic.py to try to diagnose the problem. @@ -342,7 +343,7 @@ def test_sersic_radii(): @timer -def test_sersic_flux_scaling(): +def test_sersic_flux_scaling(run_slow): """Test flux scaling for Sersic. """ # decimal point to go to for parameter value comparisons @@ -351,7 +352,7 @@ def test_sersic_flux_scaling(): test_flux = 17.9 test_sersic_trunc = [0., 8.5] - if __name__ != "__main__": + if not run_slow: # If doing a pytest run, we don't actually need to do all 4 sersic n values. # Two should be enough to notice if there is a problem, and the full list will be tested # when running python test_sersic.py to try to diagnose the problem. @@ -562,6 +563,7 @@ def test_ne(): galsim.DeVaucouleurs(half_light_radius=1.0, gsparams=gsp)] check_all_diff(gals) + @timer def test_near_05(): """Test from issue #1041, where some values of n near but not exactly equal to 0.5 would @@ -580,5 +582,4 @@ def test_near_05(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_shapelet.py b/tests/test_shapelet.py index 499bc26d5f..ff32e946e8 100644 --- a/tests/test_shapelet.py +++ b/tests/test_shapelet.py @@ -354,5 +354,4 @@ def test_ne(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_shear.py b/tests/test_shear.py index 6efd9f1423..dec7a8f78a 100644 --- a/tests/test_shear.py +++ b/tests/test_shear.py @@ -270,5 +270,4 @@ def test_shear_matrix(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_shear_position.py b/tests/test_shear_position.py index 8b2689a98e..ac799bf44a 100644 --- a/tests/test_shear_position.py +++ b/tests/test_shear_position.py @@ -125,5 +125,4 @@ def test_shear_position_image_integration_offsetwcs(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_spergel.py b/tests/test_spergel.py index 31084ce293..4f0358a813 100644 --- a/tests/test_spergel.py +++ b/tests/test_spergel.py @@ -340,5 +340,4 @@ def test_ne(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_sum.py b/tests/test_sum.py index bd9b12ea55..8b4d9a5e84 100644 --- a/tests/test_sum.py +++ b/tests/test_sum.py @@ -349,5 +349,4 @@ def test_gsparams(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_table.py b/tests/test_table.py index cd1e419f08..06c0e09a6d 100644 --- a/tests/test_table.py +++ b/tests/test_table.py @@ -1233,5 +1233,4 @@ def test_integrate_product(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_transforms.py b/tests/test_transforms.py index 0d4a2c8276..a07f55a536 100644 --- a/tests/test_transforms.py +++ b/tests/test_transforms.py @@ -96,6 +96,7 @@ def test_smallshear(): assert_raises(TypeError, gauss.shear, g1=0.1, g2=0.1, invalid=0.3) assert_raises(TypeError, gauss.shear, myShear, invalid=0.3) + @timer def test_largeshear(): """Test the application of a large shear to a Sersic profile against a known result. @@ -204,6 +205,7 @@ def test_rotate(): assert_raises(TypeError, gal.rotate) assert_raises(TypeError, gal.rotate, 34) + @timer def test_mag(): """Test the magnification (size x 1.5) of an exponential profile against a known result. @@ -614,7 +616,7 @@ def test_integer_shift_photon(): @timer -def test_flip(): +def test_flip(run_slow): """Test several ways to flip a profile """ # The Shapelet profile has the advantage of being fast and not circularly symmetric, so @@ -626,7 +628,7 @@ def test_flip(): galsim.Shapelet(sigma=0.17, order=2, bvec=[1.7, 0.01,0.03, 0.29, 0.33, -0.18]), ] - if __name__ == "__main__": + if run_slow: image_dir = './real_comparison_images' catalog_file = 'test_catalog.fits' rgc = galsim.RealGalaxyCatalog(catalog_file, dir=image_dir) @@ -967,6 +969,7 @@ def test_compound(): np.testing.assert_array_almost_equal(im3_cf.array, im3_cd.array, decimal=3) np.testing.assert_array_almost_equal(im5_cf.array, im5_cd.array, decimal=3) + @timer def test_gsparams(): """Test withGSParams with some non-default gsparams @@ -1011,5 +1014,4 @@ def test_gsparams(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_utilities.py b/tests/test_utilities.py index bfbd039f60..ad18cd6166 100644 --- a/tests/test_utilities.py +++ b/tests/test_utilities.py @@ -1487,5 +1487,4 @@ def test_merge_sorted(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_vonkarman.py b/tests/test_vonkarman.py index 3374fc2133..1030b93581 100644 --- a/tests/test_vonkarman.py +++ b/tests/test_vonkarman.py @@ -25,10 +25,10 @@ @timer -def test_vk(): +def test_vk(run_slow): """Test the generation of VonKarman profiles """ - if __name__ == "__main__": + if run_slow: lams = [300.0, 500.0, 1100.0] r0_500s = [0.05, 0.15, 0.3] L0s = [1e10, 25.0, 10.0] @@ -270,7 +270,7 @@ def vk_benchmark(): @timer -def test_vk_r0(): +def test_vk_r0(run_slow): """Test a special r0 value that resulted in an error, reported in issue #957. Note: the resolution of the bug was to add explicit split points for the first several @@ -288,7 +288,7 @@ def test_vk_r0(): vk = galsim.VonKarman(L0=25.,lam=700.,r0=r0) check_basic(vk, "VonKarman, r0=%s"%r0) - if __name__ == '__main__': + if run_slow: # Josh then tried a bunch more random triples of r0_500, lam, L0 to find more failures, # which are given in input/vk_fail.txt. r0_500_list, lam_list, L0_list = np.loadtxt('input/vk_fail.txt').T @@ -379,8 +379,8 @@ def test_low_folding_threshold(): parser = ArgumentParser() parser.add_argument("--benchmark", action='store_true', help="Run timing benchmark") - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns, parser=parser) - args = parser.parse_args() + runtests(__file__, parser=parser) + + args, unknown_args = parser.parse_known_args() if args.benchmark: vk_benchmark() diff --git a/tests/test_wcs.py b/tests/test_wcs.py index ff5699060e..35ef63ab22 100644 --- a/tests/test_wcs.py +++ b/tests/test_wcs.py @@ -344,7 +344,7 @@ def check_world(pos1, pos2, digits, err_msg): np.testing.assert_almost_equal(pos1.x, pos2.x, digits, err_msg) np.testing.assert_almost_equal(pos1.y, pos2.y, digits, err_msg) -def do_wcs_image(wcs, name, approx=False): +def do_wcs_image(wcs, name, run_slow, approx=False): print('Start image tests for WCS '+name) @@ -466,7 +466,7 @@ def do_wcs_image(wcs, name, approx=False): "Image value at center after setCenter is wrong.") # Test makeSkyImage - if __name__ != '__main__': + if not run_slow: # Use a smaller image to speed things up. im = im[galsim.BoundsI(im.xmin,im.xmin+5,im.ymin,im.ymin+5)] new_origin = (-134, 128) @@ -1161,7 +1161,7 @@ def do_celestial_wcs(wcs, name, test_pickle=True, approx=False): @timer -def test_pixelscale(): +def test_pixelscale(run_slow): """Test the PixelScale class """ scale = 0.23 @@ -1192,7 +1192,7 @@ def test_pixelscale(): do_local_wcs(wcs, ufunc, vfunc, 'PixelScale') # Check that using a wcs in the context of an image works correctly - do_wcs_image(wcs, 'PixelScale') + do_wcs_image(wcs, 'PixelScale', run_slow) # Check jacobian() jac = wcs.jacobian() @@ -1271,10 +1271,11 @@ def test_pixelscale(): do_nonlocal_wcs(wcs, ufunc, vfunc, 'OffsetWCS 3') # Check that using a wcs in the context of an image works correctly - do_wcs_image(wcs, 'OffsetWCS') + do_wcs_image(wcs, 'OffsetWCS', run_slow) + @timer -def test_shearwcs(): +def test_shearwcs(run_slow): """Test the ShearWCS class """ scale = 0.23 @@ -1312,7 +1313,7 @@ def test_shearwcs(): do_local_wcs(wcs, ufunc, vfunc, 'ShearWCS') # Check that using a wcs in the context of an image works correctly - do_wcs_image(wcs, 'ShearWCS') + do_wcs_image(wcs, 'ShearWCS', run_slow) # Check jacobian() jac = wcs.jacobian() @@ -1393,11 +1394,11 @@ def test_shearwcs(): do_nonlocal_wcs(wcs, ufunc, vfunc, 'OffsetShearWCS 3') # Check that using a wcs in the context of an image works correctly - do_wcs_image(wcs, 'OffsetShearWCS') + do_wcs_image(wcs, 'OffsetShearWCS', run_slow) @timer -def test_affinetransform(): +def test_affinetransform(run_slow): """Test the AffineTransform class """ # First a slight tweak on a simple scale factor @@ -1520,7 +1521,7 @@ def test_affinetransform(): do_jac_decomp(wcs, 'JacobianWCS 3') # Check that using a wcs in the context of an image works correctly - do_wcs_image(wcs, 'JacobianWCS') + do_wcs_image(wcs, 'JacobianWCS', run_slow) # Add both kinds of offsets x0 = -3 @@ -1535,7 +1536,7 @@ def test_affinetransform(): do_nonlocal_wcs(wcs, ufunc, vfunc, 'AffineTransform 3') # Check that using a wcs in the context of an image works correctly - do_wcs_image(wcs, 'AffineTransform') + do_wcs_image(wcs, 'AffineTransform', run_slow) # Degenerate transformation should raise some errors degen_wcs = galsim.JacobianWCS(0.2, 0.1, 0.2, 0.1) @@ -1593,7 +1594,7 @@ def __call__(self, x, y): @timer -def test_uvfunction(): +def test_uvfunction(run_slow): """Test the UVFunction class """ # First make some that are identical to simpler WCS classes: @@ -1663,7 +1664,7 @@ def test_uvfunction(): do_nonlocal_wcs(wcs, ufunc, vfunc, 'UVFunction with string funcs', test_pickle=True) # Check that using a wcs in the context of an image works correctly - do_wcs_image(wcs, 'UVFunction_string') + do_wcs_image(wcs, 'UVFunction_string', run_slow) # Also check with inverse functions. det = dudx*dvdy - dudy*dvdx @@ -1697,7 +1698,7 @@ def test_uvfunction(): do_nonlocal_wcs(wcs, ufunc2, vfunc2, 'UVFunction with origin arguments', test_pickle=False) # Check that using a wcs in the context of an image works correctly - do_wcs_image(wcs, 'UVFunction_lambda') + do_wcs_image(wcs, 'UVFunction_lambda', run_slow) # Check basic copy and == , != for UVFunction wcs2 = wcs.copy() @@ -1744,7 +1745,7 @@ def test_uvfunction(): do_nonlocal_wcs(wcs, ufunc, vfunc, 'Cubic radial UVFunction', test_pickle=False) # Check that using a wcs in the context of an image works correctly - do_wcs_image(wcs, 'UVFunction_func') + do_wcs_image(wcs, 'UVFunction_func', run_slow) # 6. Repeat with a function object rather than a regular function. # Use a different `a` parameter for u and v to make things more interesting. @@ -1756,7 +1757,7 @@ def test_uvfunction(): do_nonlocal_wcs(wcs, ufunc, vfunc, 'Cubic object UVFunction', test_pickle=False) # Check that using a wcs in the context of an image works correctly - do_wcs_image(wcs, 'UVFunction_object') + do_wcs_image(wcs, 'UVFunction_object', run_slow) # 7. Test the UVFunction that is used in demo9 to confirm that I got the # inverse function correct! @@ -1794,7 +1795,7 @@ def test_uvfunction(): " ( 5*math.sqrt(w**2+5.e3/27.)-5*w )**(1./3.))) )(math.sqrt(u**2+v**2))") wcs = galsim.UVFunction(ufuncs, vfuncs, xfuncs, yfuncs) do_nonlocal_wcs(wcs, ufunc, vfunc, 'UVFunction from demo9, string', test_pickle=True) - do_wcs_image(wcs, 'UVFunction from demo9, string') + do_wcs_image(wcs, 'UVFunction from demo9, string', run_slow) # This version doesn't work with numpy arrays because of the math functions. # This provides a test of that branch of the makeSkyImage function. @@ -1802,7 +1803,7 @@ def test_uvfunction(): vfunc = lambda x,y : 0.17 * y * (1. + 1.e-5 * math.sqrt(x**2 + y**2)) wcs = galsim.UVFunction(ufunc, vfunc) do_nonlocal_wcs(wcs, ufunc, vfunc, 'UVFunction with math funcs', test_pickle=False) - do_wcs_image(wcs, 'UVFunction_math') + do_wcs_image(wcs, 'UVFunction_math', run_slow) # 8. A non-trivial color example ufunc = lambda x,y,c: (dudx + 0.1*c)*x + dudy*y @@ -1854,8 +1855,9 @@ def test_uvfunction(): assert_raises(ValueError, wcs.toImage, galsim.PositionD(3, 3), color=0.2) assert_raises(ValueError, wcs.toImage, galsim.PositionD(6, 0), color=0.2) + @timer -def test_radecfunction(): +def test_radecfunction(run_slow): """Test the RaDecFunction class """ # Do a sterographic projection of the above UV functions around a given reference point. @@ -2084,8 +2086,8 @@ def test_radecfunction(): # Check that using a wcs in the context of an image works correctly # (Uses the last wcs2, wcs3 set in the above loops.) - do_wcs_image(wcs2, 'RaDecFunction') - do_wcs_image(wcs3, 'RaDecFunction') + do_wcs_image(wcs2, 'RaDecFunction', run_slow) + do_wcs_image(wcs3, 'RaDecFunction', run_slow) # One with invalid functions, which raise errors. (Just for coverage really.) radec_func = lambda x,y: center.deproject_rad(math.sqrt(x),math.sqrt(y), projection='lambert') @@ -2138,7 +2140,7 @@ def do_ref(wcs, ref_list, name, approx=False, image=None): @timer -def test_astropywcs(): +def test_astropywcs(run_slow): """Test the AstropyWCS class """ with warnings.catch_warnings(): @@ -2149,7 +2151,7 @@ def test_astropywcs(): # These all work, but it is quite slow, so only test a few of them for the regular unit tests. # (1.8 seconds for 4 tags.) # Test all of them when running python test_wcs.py. - if __name__ == "__main__": + if run_slow: test_tags = ['HPX', 'TAN', 'TSC', 'STG', 'ZEA', 'ARC', 'ZPN', 'SIP', 'TPV', 'TAN-PV', 'TAN-FLIP', 'REGION', 'ZTF'] # The ones that still don't work are TNX and ZPX. @@ -2181,7 +2183,7 @@ def test_astropywcs(): do_celestial_wcs(wcs, 'Astropy file '+file_name) - do_wcs_image(wcs, 'AstropyWCS_'+tag) + do_wcs_image(wcs, 'AstropyWCS_'+tag, run_slow) # Can also use an existing astropy.wcs.WCS instance to construct. # This is probably a rare use case, but could aid efficiency if you already build the @@ -2217,10 +2219,11 @@ def test_astropywcs(): # test and add 'ZPX' to the list of working astropy.wcs types above. with assert_raises(OSError): wcs = galsim.AstropyWCS(references['ZPX'][0], dir=dir) - do_wcs_image(wcs, 'AstropyWCS_ZPX') + do_wcs_image(wcs, 'AstropyWCS_ZPX', run_slow) + @timer -def test_pyastwcs(): +def test_pyastwcs(run_slow): """Test the PyAstWCS class """ try: @@ -2232,7 +2235,7 @@ def test_pyastwcs(): # These all work, but it is quite slow, so only test a few of them for the regular unit tests. # (2.4 seconds for 6 tags.) # Test all of them when running python test_wcs.py. - if __name__ == "__main__": + if run_slow: test_tags = [ 'HPX', 'TAN', 'TSC', 'STG', 'ZEA', 'ARC', 'ZPN', 'SIP', 'TPV', 'ZPX', 'TAN-PV', 'TAN-FLIP', 'REGION', 'TNX', 'ZTF' ] else: @@ -2266,7 +2269,7 @@ def test_pyastwcs(): # TAN-FLIP has an error of 4mas after write and read here, which I don't really understand. # but it's small enough an error that I don't think it's worth worrying about further. approx = tag in [ 'ZPX', 'TAN-FLIP', 'ZTF' ] - do_wcs_image(wcs, 'PyAstWCS_'+tag, approx) + do_wcs_image(wcs, 'PyAstWCS_'+tag, run_slow, approx) # Can also use an existing startlink.Ast.FrameSet instance to construct. # This is probably a rare use case, but could aid efficiency if you already open the @@ -2296,15 +2299,14 @@ def test_pyastwcs(): assert_raises(TypeError, galsim.PyAstWCS, wcsinfo=wcsinfo, header='dummy') - @timer -def test_wcstools(): +def test_wcstools(run_slow): """Test the WcsToolsWCS class """ # These all work, but it is very slow, so only test one of them for the regular unit tests. # (1.5 seconds for just the one tag.) # Test all of them when running python test_wcs.py. - if __name__ == "__main__": + if run_slow: # Note: TPV seems to work, but on one machine, repeated calls to xy2sky with the same # x,y values vary between two distinct ra,dec outputs. I have no idea what's going on, # since I thought the calculation ought to be deterministic, but it clearly something @@ -2342,7 +2344,7 @@ def test_wcstools(): do_celestial_wcs(wcs, 'WcsToolsWCS '+file_name, approx=approx) - do_wcs_image(wcs, 'WcsToolsWCS_'+tag) + do_wcs_image(wcs, 'WcsToolsWCS_'+tag, run_slow) # HPX is one of the ones that WcsToolsWCS doesn't support. with assert_raises(galsim.GalSimError): @@ -2360,9 +2362,8 @@ def test_wcstools(): assert_raises(TypeError, galsim.WcsToolsWCS, file_name, header='dummy') - @timer -def test_gsfitswcs(): +def test_gsfitswcs(run_slow): """Test the GSFitsWCS class """ # These are all relatively fast (total time for all 10 is about 1.1 seconds), @@ -2394,7 +2395,7 @@ def test_gsfitswcs(): do_celestial_wcs(wcs, 'GSFitsWCS '+file_name) - do_wcs_image(wcs, 'GSFitsWCS_'+tag) + do_wcs_image(wcs, 'GSFitsWCS_'+tag, run_slow) # tpv_odd.fits is a modified version to have (unsupported) odd powers of r. with assert_raises(galsim.GalSimNotImplementedError): @@ -2416,6 +2417,7 @@ def test_gsfitswcs(): assert_raises(TypeError, galsim.GSFitsWCS, file_name, header='dummy') assert_raises(ValueError, galsim.GSFitsWCS, _data=('invalid',0,0,0,0,0,0)) + @timer def test_inverseab_convergence(): """Test a SIP file that used to fail to converge. @@ -2490,8 +2492,9 @@ def test_inverseab_convergence(): bad = eval(str(e)[str(e).rfind('['):]) print('as a python list: ',bad) + @timer -def test_tanwcs(): +def test_tanwcs(run_slow): """Test the TanWCS function, which returns a GSFitsWCS instance. """ @@ -2508,7 +2511,7 @@ def test_tanwcs(): center = galsim.CelestialCoord(0.*galsim.radians, 0.*galsim.radians) wcs = galsim.TanWCS(affine, center) do_celestial_wcs(wcs, 'TanWCS 1') - do_wcs_image(wcs, 'TanWCS 1') + do_wcs_image(wcs, 'TanWCS 1', run_slow) # Next one with a flip and significant rotation and a large (u,v) offset dudx = 0.1432 @@ -2521,7 +2524,7 @@ def test_tanwcs(): center = galsim.CelestialCoord(3.4 * galsim.hours, -17.9 * galsim.degrees) wcs = galsim.TanWCS(affine, center) do_celestial_wcs(wcs, 'TanWCS 2') - do_wcs_image(wcs, 'TanWCS 2') + do_wcs_image(wcs, 'TanWCS 2', run_slow) # Check crossing ra=0. # Note: this worked properly even before fixing issue #1030, since GSFitsWCS keeps all @@ -2538,7 +2541,7 @@ def test_tanwcs(): center = galsim.CelestialCoord(359.99 * galsim.degrees, -37.9 * galsim.degrees) wcs = galsim.TanWCS(affine, center) do_celestial_wcs(wcs, 'TanWCS 3') - do_wcs_image(wcs, 'TanWCS 3') + do_wcs_image(wcs, 'TanWCS 3', run_slow) # Finally a really crazy one that isn't remotely regular dudx = 0.2342 @@ -2555,14 +2558,14 @@ def test_tanwcs(): center = galsim.CelestialCoord(-241.4 * galsim.hours, 87.9 * galsim.degrees) wcs = galsim.TanWCS(affine, center) do_celestial_wcs(wcs, 'TanWCS 4') - do_wcs_image(wcs, 'TanWCS 4') + do_wcs_image(wcs, 'TanWCS 4', run_slow) @timer -def test_fitswcs(): +def test_fitswcs(run_slow): """Test the FitsWCS factory function """ - if __name__ == "__main__": + if run_slow: # For more thorough unit tests (when running python test_wcs.py explicitly), this # will test everything. If you don't have everything installed (especially # PyAst, then this may fail. @@ -2598,7 +2601,7 @@ def test_fitswcs(): approx = tag in ['ZPX','ZTF'] and isinstance(wcs, galsim.PyAstWCS) do_ref(wcs, ref_list, 'FitsWCS '+tag) do_celestial_wcs(wcs, 'FitsWCS '+file_name) - do_wcs_image(wcs, 'FitsWCS_'+tag, approx) + do_wcs_image(wcs, 'FitsWCS_'+tag, run_slow, approx) # Should also be able to build the file just from a fits.read() call, which # uses FitsWCS behind the scenes. @@ -2665,7 +2668,7 @@ def check_sphere(ra1, dec1, ra2, dec2, atol=1): @timer -def test_fittedsipwcs(): +def test_fittedsipwcs(run_slow): """Test our ability to construct a WCS from x, y, ra, dec tuples """ import astropy.io.fits as fits @@ -2690,7 +2693,7 @@ def test_fittedsipwcs(): dir = 'fits_files' - if __name__ == "__main__": + if run_slow: test_tags = all_tags else: # For pytest runs, don't bother with the crazy ones. We really only care about @@ -2868,7 +2871,7 @@ def test_fittedsipwcs(): with np.testing.assert_raises(galsim.GalSimError): wcs = galsim.FittedSIPWCS(x[:9], y[:9], ra[:9], dec[:9], order=3) - if __name__ != "__main__": + if not run_slow: return # Finally, the ZPN fit isn't very good with a TAN projection. @@ -2935,6 +2938,7 @@ def test_scamp(): do_ref(wcs, ref_list, 'Scamp FitsWCS') + @timer def test_compateq(): """Test that WCS equality vs. compatibility work as physically expected. @@ -3005,6 +3009,7 @@ def test_compateq(): assert not galsim.wcs.compatible(affine,uv2) assert not galsim.wcs.compatible(affine,uv3) + @timer def test_coadd(): """ @@ -3093,6 +3098,7 @@ def test_coadd(): np.testing.assert_almost_equal(mom.moments_centroid.x, 24.5, decimal=2) np.testing.assert_almost_equal(mom.moments_centroid.y, 24.5, decimal=2) + @timer def test_lowercase(): # The WCS parsing should be insensitive to the case of the header key values. @@ -3127,8 +3133,9 @@ def test_lowercase(): [0.26298, 0.00071, -0.00072, 0.26298], atol=1.e-4) + @timer -def test_int_args(): +def test_int_args(run_slow): """Test that integer arguments for various things work correctly. """ # Some of these used to trigger @@ -3170,7 +3177,7 @@ def test_int_args(): # Before fixing #1024, this took about 0.5 sec. # Now it usually takes about 0.04 sec. Testing at 0.25 seems like a reasonable midpoint. print('Time = ',t1-t0) - if __name__ == '__main__': + if run_slow: # Don't include this in regular unit tests, since it's not really something we need # to guarantee. This timing estimate is appropriate for my laptop, but maybe not # all systems. It also fails for pypy on GHA for some reason. @@ -3191,7 +3198,7 @@ def test_int_args(): @timer -def test_razero(): +def test_razero(run_slow): """Test the makeSkyImage function near ra=0. """ # This test reproduces the problem Chris Walter found when using the LSST WCS backend @@ -3227,7 +3234,7 @@ def test_razero(): assert 0 < wcs.toWorld(galsim.PositionD(9,288)).ra / galsim.degrees < 1 do_celestial_wcs(wcs, 'Astropy file '+file_name) - do_wcs_image(wcs, 'Astropy near ra=0') + do_wcs_image(wcs, 'Astropy near ra=0', run_slow) # Test that the local wcs comes out right where ra crosses 0. image_pos = wcs.toImage(galsim.CelestialCoord(ra=0.*galsim.degrees, dec=47*galsim.degrees)) @@ -3265,9 +3272,8 @@ def test_razero(): print('-63, 208 -> ',wcs.toWorld(galsim.PositionD(-63,208))) do_celestial_wcs(wcs, 'Astropy file '+file_name) - do_wcs_image(wcs, 'Astropy near pole') + do_wcs_image(wcs, 'Astropy near pole', run_slow) if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) diff --git a/tests/test_zernike.py b/tests/test_zernike.py index 254aeaad0d..3a1c91c2ca 100644 --- a/tests/test_zernike.py +++ b/tests/test_zernike.py @@ -1554,5 +1554,4 @@ def test_dz_mean(): if __name__ == "__main__": - testfns = [v for k, v in vars().items() if k[:5] == 'test_' and callable(v)] - runtests(testfns) + runtests(__file__) From 4b6991bcf5b5bdd69fe2219c3d2d934e36277cb6 Mon Sep 17 00:00:00 2001 From: Josh Meyers Date: Mon, 16 Sep 2024 22:47:58 -0700 Subject: [PATCH 2/4] Remove doc mentions of nosetests --- docs/install.rst | 4 ---- setup.py | 24 +++++++++++------------- tests/test_config_image.py | 4 ++-- tests/test_download.py | 2 +- tests/test_main.py | 2 +- tests/test_roman.py | 4 ++-- tests/test_wcs.py | 2 +- tests/time_all_tests | 5 ----- 8 files changed, 18 insertions(+), 29 deletions(-) delete mode 100755 tests/time_all_tests diff --git a/docs/install.rst b/docs/install.rst index d7fc47ec9f..908f93a304 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -73,10 +73,6 @@ You can also run them with multiple jobs (e.g. for 4 jobs) by typing:: You need the ``pytest-xdist`` and ``pytest-timeout`` plugins for this to work. -If you prefer to use nosetests, the equivalent command is:: - - nosetests --processes=4 --process-timeout=60 test*.py - .. note:: If your system does not have ``pytest`` installed, and you do not want diff --git a/setup.py b/setup.py index 1bae8495c8..d18d9332ca 100644 --- a/setup.py +++ b/setup.py @@ -244,7 +244,7 @@ def supports_gpu(compiler, cc_type): extra_cflags = copt[cc_type] extra_lflags = lopt[cc_type] return try_compile(cpp_code, compiler, extra_cflags, extra_lflags) - + # Check for the fftw3 library in some likely places def find_fftw_lib(output=False): import distutils.sysconfig @@ -434,29 +434,29 @@ def find_eigen_dir(output=False): if output: print("Downloaded %s. Unpacking tarball."%fname) with tarfile.open(fname) as tar: - + def is_within_directory(directory, target): - + abs_directory = os.path.abspath(directory) abs_target = os.path.abspath(target) - + prefix = os.path.commonprefix([abs_directory, abs_target]) - + return prefix == abs_directory - + def safe_extract(tar, path=".", members=None, *, numeric_owner=False): # Avoid security vulnerability in tar.extractall function. # This bit of code was added by the Advanced Research Center at Trellix in PR #1188. # For more information about the security vulnerability, see # https://github.com/advisories/GHSA-gw9q-c7gh-j9vm - + for member in tar.getmembers(): member_path = os.path.join(path, member.name) if not is_within_directory(path, member_path): raise Exception("Attempted Path Traversal in Tar File") - - tar.extractall(path, members, numeric_owner=numeric_owner) - + + tar.extractall(path, members, numeric_owner=numeric_owner) + safe_extract(tar, dir) os.remove(fname) # This actually extracts into a subdirectory with a name eigen-eigen-5a0156e40feb/ @@ -1345,9 +1345,7 @@ def run_tests(self): build_dep = ['setuptools>=38,<72', 'pybind11>=2.2', 'numpy>=1.17'] run_dep = ['astropy', 'LSSTDESC.Coord'] -test_dep = ['pytest', 'pytest-xdist', 'pytest-timeout', 'nose', 'scipy', 'pyyaml'] -# Note: Even though we don't use nosetests, nose is required for some tests to work. -# cf. https://gist.github.com/dannygoldstein/e18866ebb9c39a2739f7b9f16440e2f5 +test_dep = ['pytest', 'pytest-xdist', 'pytest-timeout', 'scipy', 'pyyaml'] # If Eigen doesn't exist in the normal places, download it. find_eigen_dir(output=True) diff --git a/tests/test_config_image.py b/tests/test_config_image.py index 163e57a5a6..169f1be527 100644 --- a/tests/test_config_image.py +++ b/tests/test_config_image.py @@ -2095,7 +2095,7 @@ def test_index_key(run_slow): images1 = [ galsim.fits.readMulti('output/index_key%02d.fits'%n) for n in range(nfiles) ] if run_slow: - # For nose tests skip these 3 to save some time. + # For pytest tests, skip these 3 to save some time. # images5 is really the hardest test, and images1 is the easiest, so those two will # give good diagnostics for any errors. @@ -2839,7 +2839,7 @@ def test_chromatic(run_slow): if run_slow: bp_file = 'LSST_r.dat' else: - # In nosetests, use a simple bandpass to go faster. + # In pytest, use a simple bandpass to go faster. bp_file = 'chromatic_reference_images/simple_bandpass.dat' # First check a chromatic galaxy with a regular PSF. diff --git a/tests/test_download.py b/tests/test_download.py index 4583f9e58b..516d15a4c1 100644 --- a/tests/test_download.py +++ b/tests/test_download.py @@ -80,7 +80,7 @@ def test_args(): assert args.nolink is True # Some invalid parameters - # To avoid ugly text output during nosetests runs, redirect stderr to stdout for a moment. + # To avoid ugly text output during pytest runs, redirect stderr to stdout for a moment. sys_stderr = sys.stderr sys.stderr = sys.stdout with assert_raises(SystemExit): diff --git a/tests/test_main.py b/tests/test_main.py index 302321495e..2b9f78dc02 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -138,7 +138,7 @@ def test_args(): galsim.main.parse_args([config_file, '-j', '3']) # The ones handled by ArgumentParser raise SystemExit and print to stderr - # To avoid ugly text output during nosetests runs, redirect stderr to stdout for a moment. + # To avoid ugly text output during pytest runs, redirect stderr to stdout for a moment. sys_stderr = sys.stderr sys.stderr = sys.stdout with assert_raises(SystemExit): diff --git a/tests/test_roman.py b/tests/test_roman.py index 115fb4d09a..96f52ada07 100644 --- a/tests/test_roman.py +++ b/tests/test_roman.py @@ -645,7 +645,7 @@ def test_roman_psfs(run_slow): # - fully chromatic PSFs with interpolation, but only interpolating between two wavelengths. # - achromatic PSFs. # - # We also only test pupil_bin=4,8 in nosetests runs. Tests of pupil_bin=1,2 are done in + # We also only test pupil_bin=4,8 in pytest runs. Tests of pupil_bin=1,2 are done in # __main__ runs. # Providing a wavelength returns achromatic PSFs @@ -748,7 +748,7 @@ def test_roman_psfs(run_slow): { 'pupil_bin':8 }, ] if run_slow: - # A few more that are too slow to run in regular nosetests + # A few more that are too slow to run in regular pytest kwargs_list.extend([ { 'pupil_bin':1 }, { 'pupil_bin':2 }, diff --git a/tests/test_wcs.py b/tests/test_wcs.py index 35ef63ab22..ef037e2270 100644 --- a/tests/test_wcs.py +++ b/tests/test_wcs.py @@ -486,7 +486,7 @@ def do_wcs_image(wcs, name, run_slow, approx=False): # used to be a problem if the wcs returned ra values that jump from 360 to 0. # Not very stringent test, since we're just checking that we don't have some pixels # that are orders of magnitude different from the average. So rtol=2 is good. - # (1 is fine for the nosetests runs, but one of the edge cases fails in main runs. It's not + # (1 is fine for the pytest runs, but one of the edge cases fails in main runs. It's not # a problem I think, just one of the weird wcs types has a more variable pixel area.) np.testing.assert_allclose(im.array, area*sky_level, rtol=2) diff --git a/tests/time_all_tests b/tests/time_all_tests deleted file mode 100755 index 47c88308f0..0000000000 --- a/tests/time_all_tests +++ /dev/null @@ -1,5 +0,0 @@ -#/bin/bash -#time run_all_tests | grep time | sort -n -k 5 | gawk '{print; n++; sum+=$5} END { print "total time for",n,"tests = ",sum }' - -# Another option... -time nosetests -s | grep time | sort -n -k 5 | gawk '{print; n++; sum+=$5} END { print "total time for",n,"tests = ",sum }' From 21216f251c1befdf6875d17931f711b46b18c4ab Mon Sep 17 00:00:00 2001 From: Josh Meyers Date: Mon, 16 Sep 2024 22:56:50 -0700 Subject: [PATCH 3/4] See if we can really excise nosetests --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index acfc5b2f00..3c470667cb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -156,7 +156,7 @@ jobs: # Extra packages needed for testing pip install -U -r test_requirements.txt - pip install -U nose coverage + pip install -U coverage pip install -U matplotlib @@ -208,7 +208,7 @@ jobs: - name: Check shared library if: matrix.py == 3.8 run: | - # On a few systems (arbitrarily py3.8, where we also chec mac and clang), + # On a few systems (arbitrarily py3.8, where we also check mac and clang), # check the shared library creation and link. GALSIM_BUILD_SHARED=1 python setup.py install From 59d8550f02b88382314a8e6a63cb93a2fcc3a688 Mon Sep 17 00:00:00 2001 From: Josh Meyers Date: Tue, 17 Sep 2024 13:38:52 -0700 Subject: [PATCH 4/4] Improve python test_blah.py output --- tests/galsim_test_helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/galsim_test_helpers.py b/tests/galsim_test_helpers.py index 8d8860ac02..105a538d98 100644 --- a/tests/galsim_test_helpers.py +++ b/tests/galsim_test_helpers.py @@ -403,7 +403,7 @@ def runtests(filename, parser=None): parser.add_argument('--profile', action='store_true', help='Profile tests') parser.add_argument('--prof_out', default=None, help="Profiler output file") args, unknown_args = parser.parse_known_args() - pytest_args = [filename] + unknown_args + ["--run_slow"] + pytest_args = [filename] + unknown_args + ["--run_slow", "--tb=short", "-s"] if args.profile: import cProfile, pstats