From d0b1b8788b8aa61cf946b001db9ae51ad153b90e Mon Sep 17 00:00:00 2001 From: Ilya Baryshnikov Date: Wed, 23 Sep 2026 12:32:25 +0300 Subject: [PATCH 1/5] add tests --- cabal-install/tests/IntegrationTests2.hs | 26 +++++++++++++++++++ .../targets/tests-and-no-tests/P.hs | 1 + .../targets/tests-and-no-tests/Test.hs | 4 +++ .../targets/tests-and-no-tests/cabal.project | 1 + .../targets/tests-and-no-tests/p.cabal | 13 ++++++++++ .../targets/tests-and-no-tests/q/Q.hs | 1 + .../targets/tests-and-no-tests/q/q.cabal | 8 ++++++ 7 files changed, 54 insertions(+) create mode 100644 cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/P.hs create mode 100644 cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/Test.hs create mode 100644 cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/cabal.project create mode 100644 cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/p.cabal create mode 100644 cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/q/Q.hs create mode 100644 cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/q/q.cabal diff --git a/cabal-install/tests/IntegrationTests2.hs b/cabal-install/tests/IntegrationTests2.hs index a3d9e20820a..b5cc01c38af 100644 --- a/cabal-install/tests/IntegrationTests2.hs +++ b/cabal-install/tests/IntegrationTests2.hs @@ -1426,6 +1426,32 @@ testTargetProblemsTest config reportSubCase = do , (CmdTest.noTestsProblem, mkTargetPackage "q-0.1") ] + reportSubCase "pkg with tests and pkg without tests" + do + (_, elaboratedPlan, _) <- planProject "targets/tests-and-no-tests" config + let resolveTargets = + resolveTargetsFromSolver + CmdTest.selectPackageTargets + CmdTest.selectComponentTarget + elaboratedPlan + Nothing + requestedSelectors = + [ mkTargetPackage "p-0.1" + , mkTargetPackage "q-0.1" + ] + targets <- case resolveTargets requestedSelectors of + Right ts -> + assertFailure $ "expected target problems, but got: " ++ show ts + Left problems -> + CmdTest.reportTargetProblems + testVerbosity + (Flag False) + requestedSelectors + resolveTargets + problems + distinctTargetComponents targets + @?= Set.fromList [("p-0.1-inplace-p-tests", CTestName "p-tests")] + reportSubCase "not a test" assertProjectTargetProblems "targets/variety" diff --git a/cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/P.hs b/cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/P.hs new file mode 100644 index 00000000000..fc4877ad85e --- /dev/null +++ b/cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/P.hs @@ -0,0 +1 @@ +module P where diff --git a/cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/Test.hs b/cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/Test.hs new file mode 100644 index 00000000000..d82a4bd93b7 --- /dev/null +++ b/cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/Test.hs @@ -0,0 +1,4 @@ +module Main where + +main :: IO () +main = return () diff --git a/cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/cabal.project b/cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/cabal.project new file mode 100644 index 00000000000..97e14438660 --- /dev/null +++ b/cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/cabal.project @@ -0,0 +1 @@ +packages: ./ q/ diff --git a/cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/p.cabal b/cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/p.cabal new file mode 100644 index 00000000000..2a6f2ad133a --- /dev/null +++ b/cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/p.cabal @@ -0,0 +1,13 @@ +cabal-version: 3.8 +name: p +version: 0.1 +build-type: Simple + +library + exposed-modules: P + build-depends: base + +test-suite p-tests + type: exitcode-stdio-1.0 + main-is: Test.hs + build-depends: base diff --git a/cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/q/Q.hs b/cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/q/Q.hs new file mode 100644 index 00000000000..26669d9c8a8 --- /dev/null +++ b/cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/q/Q.hs @@ -0,0 +1 @@ +module Q where diff --git a/cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/q/q.cabal b/cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/q/q.cabal new file mode 100644 index 00000000000..5255d4fdea9 --- /dev/null +++ b/cabal-install/tests/IntegrationTests2/targets/tests-and-no-tests/q/q.cabal @@ -0,0 +1,8 @@ +cabal-version: 3.8 +name: q +version: 0.1 +build-type: Simple + +library + exposed-modules: Q + build-depends: base From 071f649b1cff16794a67410b773fb64d36777b33 Mon Sep 17 00:00:00 2001 From: Ilya Baryshnikov Date: Wed, 23 Sep 2026 12:32:49 +0300 Subject: [PATCH 2/5] fix no tests run --- .../src/Distribution/Client/CmdTest.hs | 70 +++++++++++++------ 1 file changed, 50 insertions(+), 20 deletions(-) diff --git a/cabal-install/src/Distribution/Client/CmdTest.hs b/cabal-install/src/Distribution/Client/CmdTest.hs index 6ad41678849..6c87d0bb3c9 100644 --- a/cabal-install/src/Distribution/Client/CmdTest.hs +++ b/cabal-install/src/Distribution/Client/CmdTest.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE RecordWildCards #-} @@ -11,6 +12,7 @@ module Distribution.Client.CmdTest , isSubComponentProblem , notTestProblem , noTestsProblem + , reportTargetProblems , selectPackageTargets , selectComponentTarget ) where @@ -57,6 +59,7 @@ import Distribution.Simple.Setup import Distribution.Simple.Utils ( dieWithException , notice + , ordNub , warn , wrapText ) @@ -142,14 +145,17 @@ testAction flags@NixStyleFlags{..} targetStrings globalFlags = do -- Interpret the targets on the command line as test targets -- (as opposed to say build or haddock targets). + let resolveTargets = + resolveTargetsFromSolver + selectPackageTargets + selectComponentTarget + elaboratedPlan + Nothing targets <- - either (reportTargetProblems verbosity failWhenNoTestSuites) return $ - resolveTargetsFromSolver - selectPackageTargets - selectComponentTarget - elaboratedPlan - Nothing - targetSelectors + either + (reportTargetProblems verbosity failWhenNoTestSuites targetSelectors resolveTargets) + return + $ resolveTargets targetSelectors let elaboratedPlan' = pruneInstallPlanToTargets @@ -255,22 +261,46 @@ isSubComponentProblem pkgid name subcomponent = CustomTargetProblem $ TargetProblemIsSubComponent pkgid name subcomponent -reportTargetProblems :: Verbosity -> Flag Bool -> [TestTargetProblem] -> IO a -reportTargetProblems verbosity failWhenNoTestSuites problems = - case (failWhenNoTestSuites, problems) of - (Flag True, [CustomTargetProblem (TargetProblemNoTests _)]) -> - dieWithException verbosity $ ReportTargetProblems problemsMessage - (_, [CustomTargetProblem (TargetProblemNoTests selector)]) -> do - notice verbosity (renderAllowedNoTestsProblem selector) - System.Exit.exitSuccess - (_, _) -> dieWithException verbosity $ ReportTargetProblems problemsMessage +-- | Targets that do not contain any test suites do not abort the command +-- (unless @--test-fail-when-no-test-suites@ is given): they are skipped with +-- a notice, and the remaining requested targets are resolved and tested. +reportTargetProblems + :: Verbosity + -> Flag Bool + -- ^ @--test-fail-when-no-test-suites@ + -> [TargetSelector] + -- ^ the target selectors requested on the command line + -> ([TargetSelector] -> Either [TestTargetProblem] TargetsMap) + -- ^ how to resolve (a subset of) the requested targets + -> [TestTargetProblem] + -> IO TargetsMap +reportTargetProblems verbosity failWhenNoTestSuites targetSelectors resolveTargets problems = + if failWhenNoTestSuites /= Flag True && null otherProblems && not (null noTestsSelectors) + then do + for_ noTestsSelectors $ notice verbosity . renderAllowedNoTestsProblem + + let remainingSelectors = filter (`notElem` noTestsSelectors) targetSelectors + if null remainingSelectors + then System.Exit.exitSuccess + else + either + (reportTargetProblems verbosity failWhenNoTestSuites remainingSelectors resolveTargets) + return + $ resolveTargets remainingSelectors + else dieWithException verbosity $ ReportTargetProblems problemsMessage where problemsMessage = unlines . map renderTestTargetProblem $ problems --- | Unless @--test-fail-when-no-test-suites@ flag is passed, we don't --- @die@ when the target problem is 'TargetProblemNoTests'. --- Instead, we display a notice saying that no tests have run and --- indicate how this behaviour was enabled. + (noTestsProblems, otherProblems) = + flip partition problems $ \case + (CustomTargetProblem (TargetProblemNoTests _)) -> True + _ -> False + + noTestsSelectors = + ordNub [selector | CustomTargetProblem (TargetProblemNoTests selector) <- noTestsProblems] + +-- | The message displayed for each skipped target that does not contain +-- any test suites. renderAllowedNoTestsProblem :: TargetSelector -> String renderAllowedNoTestsProblem selector = "No tests to run for " ++ renderTargetSelector selector From 9013f05f2c58340c8f1394c6eb6d8280b977ed70 Mon Sep 17 00:00:00 2001 From: Ilya Baryshnikov Date: Wed, 23 Sep 2026 12:33:10 +0300 Subject: [PATCH 3/5] add changelog --- changelog.d/12300.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 changelog.d/12300.md diff --git a/changelog.d/12300.md b/changelog.d/12300.md new file mode 100644 index 00000000000..8ced90da3a9 --- /dev/null +++ b/changelog.d/12300.md @@ -0,0 +1,16 @@ +--- +synopsis: "`cabal test` runs the tests of the targets that have them" +packages: [cabal-install] +prs: 12300 +issues: 11858 +--- + +`cabal test` used to abort with a successful exit status when one of the requested targets did not contain any test suites, silently skipping the tests of the other targets. Such targets are now skipped with a notice ("No tests to run for ...") and the tests of the remaining targets run. + +```pre +$ cabal test pkg-with-tests pkg-without-tests +No tests to run for the package pkg-without-tests-0.1.0.0 +Running 1 test suites... +Test suite pkg-with-tests-test: PASS +1 of 1 test suites (1 of 1 test cases) passed. +``` From aa371faa5436998084423762fc8b4b05a159186d Mon Sep 17 00:00:00 2001 From: Ilya Baryshnikov Date: Fri, 25 Sep 2026 14:40:18 +0000 Subject: [PATCH 4/5] update doc --- changelog.d/12300.md | 7 ++++++- doc/cabal-commands.rst | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/changelog.d/12300.md b/changelog.d/12300.md index 8ced90da3a9..9801f1452dc 100644 --- a/changelog.d/12300.md +++ b/changelog.d/12300.md @@ -5,7 +5,12 @@ prs: 12300 issues: 11858 --- -`cabal test` used to abort with a successful exit status when one of the requested targets did not contain any test suites, silently skipping the tests of the other targets. Such targets are now skipped with a notice ("No tests to run for ...") and the tests of the remaining targets run. +`cabal test` used to abort with a successful exit status when one of the +requested targets did not contain any test suites, silently skipping the +tests of the other targets. Such targets are now skipped with a notice +("No tests to run for ...") and the tests of the remaining targets run. +The same applies to the `:tests` form of package targets (e.g. `q:tests`), +which used to be an error. ```pre $ cabal test pkg-with-tests pkg-without-tests diff --git a/doc/cabal-commands.rst b/doc/cabal-commands.rst index 0c4fb040375..0989acb7686 100644 --- a/doc/cabal-commands.rst +++ b/doc/cabal-commands.rst @@ -1388,6 +1388,29 @@ after ensuring they are up to date and building them, if necessary. target will select all packages of the project and, from those, test all their test suites. +Not every target contains test suites: a package can have a library or +executables but no test suites at all. By default this is not an error: +``cabal test`` skips such targets with a ``No tests to run for ...`` notice +and still builds and runs the test suites of the remaining targets:: + + $ cabal test pkg-with-tests pkg-without-tests + No tests to run for the package pkg-without-tests-0.1.0.0 + ... + Running 1 test suites... + Test suite pkg-with-tests-test: PASS + 1 of 1 test suites (1 of 1 test cases) passed. + +If none of the requested targets contain any test suites, nothing is built +or run: ``cabal test`` prints a notice for each target and exits +successfully. The same applies to the ``:tests`` filtered form of a package +target, e.g. ``q:tests``. + +Because a successful exit does not imply that any test suite ran, this +behaviour can hide skipped tests, e.g. in CI. To treat such targets as +errors instead, pass ``--test-fail-when-no-test-suites``: ``cabal test`` +then exits with failure when any of the requested targets does not contain +any test suites, instead of skipping it. + ``cabal test`` inherits flags of the ``test`` subcommand of ``Setup.hs`` (:ref:`see the corresponding section `) with one caveat: every ``Setup.hs test`` flag receives the ``test-`` prefix if it already does From f955f3da231e1094f2e563705ab0bfaf33eb558a Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Sat, 26 Sep 2026 06:55:21 +0000 Subject: [PATCH 5/5] Add NoTests package test and skip empty :tests targets Adds cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests covering cabal v2-test with the p q, all, all:tests, q and q:tests targets, each with and without --test-fail-when-no-test-suites. Kind-filtered package targets that come up empty (q:tests when q has no test suites, all:tests when no package has test suites) are now skipped with a notice like plain package targets, instead of failing the command. --- .../src/Distribution/Client/CmdTest.hs | 14 ++- .../CmdTest/NoTests/cabal.all-tests.out | 13 +++ .../NoTests/cabal.all-tests_+failflag.out | 13 +++ .../NewBuild/CmdTest/NoTests/cabal.all.out | 13 +++ .../CmdTest/NoTests/cabal.all_+failflag.out | 13 +++ .../CmdTest/NoTests/cabal.mixed-tests.out | 14 +++ .../NoTests/cabal.mixed-tests_+failflag.out | 4 + .../NewBuild/CmdTest/NoTests/cabal.mixed.out | 14 +++ .../CmdTest/NoTests/cabal.mixed_+failflag.out | 4 + .../NoTests/cabal.only-no-tests-tests.out | 3 + .../cabal.only-no-tests-tests_+failflag.out | 4 + .../CmdTest/NoTests/cabal.only-no-tests.out | 3 + .../NoTests/cabal.only-no-tests_+failflag.out | 4 + .../NewBuild/CmdTest/NoTests/cabal.project | 1 + .../NewBuild/CmdTest/NoTests/cabal.test.hs | 105 ++++++++++++++++++ .../NewBuild/CmdTest/NoTests/p/P.hs | 1 + .../NewBuild/CmdTest/NoTests/p/p.cabal | 16 +++ .../NewBuild/CmdTest/NoTests/p/test/Main.hs | 4 + .../NewBuild/CmdTest/NoTests/q/Q.hs | 1 + .../NewBuild/CmdTest/NoTests/q/q.cabal | 9 ++ 20 files changed, 249 insertions(+), 4 deletions(-) create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.all-tests.out create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.all-tests_+failflag.out create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.all.out create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.all_+failflag.out create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.mixed-tests.out create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.mixed-tests_+failflag.out create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.mixed.out create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.mixed_+failflag.out create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.only-no-tests-tests.out create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.only-no-tests-tests_+failflag.out create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.only-no-tests.out create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.only-no-tests_+failflag.out create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.project create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.test.hs create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/p/P.hs create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/p/p.cabal create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/p/test/Main.hs create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/q/Q.hs create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/q/q.cabal diff --git a/cabal-install/src/Distribution/Client/CmdTest.hs b/cabal-install/src/Distribution/Client/CmdTest.hs index 6c87d0bb3c9..217a3999876 100644 --- a/cabal-install/src/Distribution/Client/CmdTest.hs +++ b/cabal-install/src/Distribution/Client/CmdTest.hs @@ -184,16 +184,22 @@ selectPackageTargets -> [AvailableTarget k] -> Either TestTargetProblem [k] selectPackageTargets targetSelector targets - -- If there are any buildable test-suite targets then we select those + -- If there are any buildable test-suite targets then we select those. | not (null targetsTestsBuildable) = Right targetsTestsBuildable - -- If there are test-suites but none are buildable then we report those + -- If there are test-suites but none are buildable then we report those. | not (null targetsTests) = Left (TargetProblemNoneEnabled targetSelector targetsTests) - -- If there are no test-suite but some other targets then we report that + -- If there are no test-suite but some other targets then we report that. | not (null targets) = Left (noTestsProblem targetSelector) - -- If there are no targets at all then we report that + -- If pkg:tests comes up empty we report no tests. + | TargetPackage _ _ (Just TestKind) <- targetSelector = + Left (noTestsProblem targetSelector) + -- If all:tests comes up empty we report no tests. + | TargetAllPackages (Just TestKind) <- targetSelector = + Left (noTestsProblem targetSelector) + -- If there are no targets at all then we report that. | otherwise = Left (TargetProblemNoTargets targetSelector) where diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.all-tests.out b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.all-tests.out new file mode 100644 index 00000000000..59f930a8506 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.all-tests.out @@ -0,0 +1,13 @@ +# cabal v2-test +Resolving dependencies... +Build profile: -w ghc- -O1 +In order, the following will be built: + - p-0.1 (test:p-tests) (first run) +Configuring test suite 'p-tests' for p-0.1... +Preprocessing test suite 'p-tests' for p-0.1... +Building test suite 'p-tests' for p-0.1... +Running 1 test suites... +Test suite p-tests: RUNNING... +Test suite p-tests: PASS +Test suite logged to: /cabal.all-tests.dist/work/./dist/build//ghc-/p-0.1/t/p-tests/test/p-0.1-p-tests.log +1 of 1 test suites (1 of 1 test cases) passed. diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.all-tests_+failflag.out b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.all-tests_+failflag.out new file mode 100644 index 00000000000..8839ff8dbf1 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.all-tests_+failflag.out @@ -0,0 +1,13 @@ +# cabal v2-test +Resolving dependencies... +Build profile: -w ghc- -O1 +In order, the following will be built: + - p-0.1 (test:p-tests) (first run) +Configuring test suite 'p-tests' for p-0.1... +Preprocessing test suite 'p-tests' for p-0.1... +Building test suite 'p-tests' for p-0.1... +Running 1 test suites... +Test suite p-tests: RUNNING... +Test suite p-tests: PASS +Test suite logged to: /cabal.all-tests_+failflag.dist/work/./dist/build//ghc-/p-0.1/t/p-tests/test/p-0.1-p-tests.log +1 of 1 test suites (1 of 1 test cases) passed. diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.all.out b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.all.out new file mode 100644 index 00000000000..ac84330cf4f --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.all.out @@ -0,0 +1,13 @@ +# cabal v2-test +Resolving dependencies... +Build profile: -w ghc- -O1 +In order, the following will be built: + - p-0.1 (test:p-tests) (first run) +Configuring test suite 'p-tests' for p-0.1... +Preprocessing test suite 'p-tests' for p-0.1... +Building test suite 'p-tests' for p-0.1... +Running 1 test suites... +Test suite p-tests: RUNNING... +Test suite p-tests: PASS +Test suite logged to: /cabal.all.dist/work/./dist/build//ghc-/p-0.1/t/p-tests/test/p-0.1-p-tests.log +1 of 1 test suites (1 of 1 test cases) passed. diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.all_+failflag.out b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.all_+failflag.out new file mode 100644 index 00000000000..4b5d7670db6 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.all_+failflag.out @@ -0,0 +1,13 @@ +# cabal v2-test +Resolving dependencies... +Build profile: -w ghc- -O1 +In order, the following will be built: + - p-0.1 (test:p-tests) (first run) +Configuring test suite 'p-tests' for p-0.1... +Preprocessing test suite 'p-tests' for p-0.1... +Building test suite 'p-tests' for p-0.1... +Running 1 test suites... +Test suite p-tests: RUNNING... +Test suite p-tests: PASS +Test suite logged to: /cabal.all_+failflag.dist/work/./dist/build//ghc-/p-0.1/t/p-tests/test/p-0.1-p-tests.log +1 of 1 test suites (1 of 1 test cases) passed. diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.mixed-tests.out b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.mixed-tests.out new file mode 100644 index 00000000000..9f655fc1042 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.mixed-tests.out @@ -0,0 +1,14 @@ +# cabal v2-test +Resolving dependencies... +No tests to run for the test suites in the package q-0.1 +Build profile: -w ghc- -O1 +In order, the following will be built: + - p-0.1 (test:p-tests) (first run) +Configuring test suite 'p-tests' for p-0.1... +Preprocessing test suite 'p-tests' for p-0.1... +Building test suite 'p-tests' for p-0.1... +Running 1 test suites... +Test suite p-tests: RUNNING... +Test suite p-tests: PASS +Test suite logged to: /cabal.mixed-tests.dist/work/./dist/build//ghc-/p-0.1/t/p-tests/test/p-0.1-p-tests.log +1 of 1 test suites (1 of 1 test cases) passed. diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.mixed-tests_+failflag.out b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.mixed-tests_+failflag.out new file mode 100644 index 00000000000..8167588ab53 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.mixed-tests_+failflag.out @@ -0,0 +1,4 @@ +# cabal v2-test +Resolving dependencies... +Error: [Cabal-7043] +Cannot run tests for the target 'q:tests' which refers to the test suites in the package q-0.1 because it does not contain any test suites. diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.mixed.out b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.mixed.out new file mode 100644 index 00000000000..f0ffe74509f --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.mixed.out @@ -0,0 +1,14 @@ +# cabal v2-test +Resolving dependencies... +No tests to run for the package q-0.1 +Build profile: -w ghc- -O1 +In order, the following will be built: + - p-0.1 (test:p-tests) (first run) +Configuring test suite 'p-tests' for p-0.1... +Preprocessing test suite 'p-tests' for p-0.1... +Building test suite 'p-tests' for p-0.1... +Running 1 test suites... +Test suite p-tests: RUNNING... +Test suite p-tests: PASS +Test suite logged to: /cabal.mixed.dist/work/./dist/build//ghc-/p-0.1/t/p-tests/test/p-0.1-p-tests.log +1 of 1 test suites (1 of 1 test cases) passed. diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.mixed_+failflag.out b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.mixed_+failflag.out new file mode 100644 index 00000000000..d0d32e6b1d1 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.mixed_+failflag.out @@ -0,0 +1,4 @@ +# cabal v2-test +Resolving dependencies... +Error: [Cabal-7043] +Cannot run tests for the target 'q' which refers to the package q-0.1 because it does not contain any test suites. diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.only-no-tests-tests.out b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.only-no-tests-tests.out new file mode 100644 index 00000000000..2cd1d6e700a --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.only-no-tests-tests.out @@ -0,0 +1,3 @@ +# cabal v2-test +Resolving dependencies... +No tests to run for the test suites in the package q-0.1 diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.only-no-tests-tests_+failflag.out b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.only-no-tests-tests_+failflag.out new file mode 100644 index 00000000000..8167588ab53 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.only-no-tests-tests_+failflag.out @@ -0,0 +1,4 @@ +# cabal v2-test +Resolving dependencies... +Error: [Cabal-7043] +Cannot run tests for the target 'q:tests' which refers to the test suites in the package q-0.1 because it does not contain any test suites. diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.only-no-tests.out b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.only-no-tests.out new file mode 100644 index 00000000000..c3e20df4909 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.only-no-tests.out @@ -0,0 +1,3 @@ +# cabal v2-test +Resolving dependencies... +No tests to run for the package q-0.1 diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.only-no-tests_+failflag.out b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.only-no-tests_+failflag.out new file mode 100644 index 00000000000..d0d32e6b1d1 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.only-no-tests_+failflag.out @@ -0,0 +1,4 @@ +# cabal v2-test +Resolving dependencies... +Error: [Cabal-7043] +Cannot run tests for the target 'q' which refers to the package q-0.1 because it does not contain any test suites. diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.project b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.project new file mode 100644 index 00000000000..085b1161f41 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.project @@ -0,0 +1 @@ +packages: p q diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.test.hs b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.test.hs new file mode 100644 index 00000000000..f5daaa216bf --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/cabal.test.hs @@ -0,0 +1,105 @@ +import Test.Cabal.Prelude + +-- Package p has a test suite, package q does not. +-- +-- Every scenario is run as is and, in the mode with the +-- "_+failflag" suffix, with --test-fail-when-no-test-suites. +-- The flag turns a skipped target into an error and is otherwise inert. + +flag :: String +flag = "--test-fail-when-no-test-suites" + +-- The X:tests target variants of the X targets must behave the same as +-- without the :tests filter, so the assertions are shared. Only the rendering +-- of the target in the notice or error message differs. + +-- q is skipped with a notice, p is not, and the tests of p run. +assertSkippedQRanP :: String -> String -> Result -> TestM () +assertSkippedQRanP q p res = do + assertOutputContains ("No tests to run for " ++ q) res + assertOutputDoesNotContain ("No tests to run for " ++ p) res + assertOutputContains "Test suite p-tests: PASS" res + +-- q having no tests is an error and the tests of p do not run. +assertFailedQNotRanP :: String -> Result -> TestM () +assertFailedQNotRanP q res = do + assertOutputContains ("Cannot run tests for the target '" ++ q ++ "'") res + assertOutputDoesNotContain "Test suite p-tests: PASS" res + +-- Nothing is skipped and the tests of p run. +assertSkippedNoneRanP :: Result -> TestM () +assertSkippedNoneRanP res = do + assertOutputDoesNotContain "No tests to run" res + assertOutputContains "Test suite p-tests: PASS" res + +-- q is skipped with a notice and the tests of p do not run. +assertSkippedQNotRanP :: String -> Result -> TestM () +assertSkippedQNotRanP q res = do + assertOutputContains ("No tests to run for " ++ q) res + assertOutputDoesNotContain "Test suite p-tests" res + +-- q having no tests is an error. +assertFailedQ :: String -> Result -> TestM () +assertFailedQ q res = + assertOutputContains ("Cannot run tests for the target '" ++ q ++ "'") res + +main = do + -- Requesting both must skip q with a notice and still run the tests of p. + cabalTest' "mixed" $ do + res <- cabal' "v2-test" ["p", "q"] + assertSkippedQRanP "the package q-0.1" "the package p-0.1" res + + -- Same with :tests. + cabalTest' "mixed-tests" $ do + res <- cabal' "v2-test" ["p:tests", "q:tests"] + assertSkippedQRanP "the test suites in the package q-0.1" "the test suites in the package p-0.1" res + + -- With the flag q having no tests triggers the error. + cabalTest' "mixed_+failflag" $ do + res <- fails $ cabal' "v2-test" ["p", "q", flag] + assertFailedQNotRanP "q" res + + -- Same with :tests. + cabalTest' "mixed-tests_+failflag" $ do + res <- fails $ cabal' "v2-test" ["p:tests", "q:tests", flag] + assertFailedQNotRanP "q:tests" res + + -- With "all" as target, the tests of p are found. + cabalTest' "all" $ do + res <- cabal' "v2-test" ["all"] + assertSkippedNoneRanP res + + -- Same thing even with the fail flag. + cabalTest' "all_+failflag" $ do + res <- cabal' "v2-test" ["all", flag] + assertSkippedNoneRanP res + + -- Same again with the :tests filter. + cabalTest' "all-tests" $ do + res <- cabal' "v2-test" ["all:tests"] + assertSkippedNoneRanP res + + -- No difference even with the fail flag. + cabalTest' "all-tests_+failflag" $ do + res <- cabal' "v2-test" ["all:tests", flag] + assertSkippedNoneRanP res + + -- When no target has tests, the command succeeds and reports skipped targets. + cabalTest' "only-no-tests" $ do + res <- cabal' "v2-test" ["q"] + assertSkippedQNotRanP "the package q-0.1" res + + -- Same with :tests. + cabalTest' "only-no-tests-tests" $ do + res <- cabal' "v2-test" ["q:tests"] + assertSkippedQNotRanP "the test suites in the package q-0.1" res + + -- The fail flag causes the command to fail when no tests are found. + cabalTest' "only-no-tests_+failflag" $ do + res <- fails $ cabal' "v2-test" ["q", flag] + assertFailedQ "q" res + + -- Same with :tests. + cabalTest' "only-no-tests-tests_+failflag" $ do + res <- fails $ cabal' "v2-test" ["q:tests", flag] + assertFailedQ "q:tests" res diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/p/P.hs b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/p/P.hs new file mode 100644 index 00000000000..fc4877ad85e --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/p/P.hs @@ -0,0 +1 @@ +module P where diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/p/p.cabal b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/p/p.cabal new file mode 100644 index 00000000000..de85d3be419 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/p/p.cabal @@ -0,0 +1,16 @@ +cabal-version: 3.0 +name: p +version: 0.1 +build-type: Simple + +library + exposed-modules: P + build-depends: base + default-language: Haskell2010 + +test-suite p-tests + type: exitcode-stdio-1.0 + hs-source-dirs: test + main-is: Main.hs + build-depends: base + default-language: Haskell2010 diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/p/test/Main.hs b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/p/test/Main.hs new file mode 100644 index 00000000000..d82a4bd93b7 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/p/test/Main.hs @@ -0,0 +1,4 @@ +module Main where + +main :: IO () +main = return () diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/q/Q.hs b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/q/Q.hs new file mode 100644 index 00000000000..26669d9c8a8 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/q/Q.hs @@ -0,0 +1 @@ +module Q where diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/q/q.cabal b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/q/q.cabal new file mode 100644 index 00000000000..88053fc3cac --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdTest/NoTests/q/q.cabal @@ -0,0 +1,9 @@ +cabal-version: 3.0 +name: q +version: 0.1 +build-type: Simple + +library + exposed-modules: Q + build-depends: base + default-language: Haskell2010