From 88b2495c879f3692d51a0c224e3643ad7266f635 Mon Sep 17 00:00:00 2001 From: Nico Verbruggen Date: Mon, 25 Aug 2025 17:45:56 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20WIP:=20Change=20some=20tes?= =?UTF-8?q?ts=20to=20Swift=20Testing,=20add=20`TestBundle`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PHP Monitor.xcodeproj/project.pbxproj | 34 ++++++++++--- tests/Shared/TestBundle.swift | 50 +++++++++++++++++++ .../unit/{ => _ST}/Commands/CommandTest.swift | 16 +++--- .../_ST/Integration}/PackagistTest.swift | 1 + .../Parsers/ValetConfigurationTest.swift | 20 ++++---- 5 files changed, 98 insertions(+), 23 deletions(-) create mode 100644 tests/Shared/TestBundle.swift rename tests/unit/{ => _ST}/Commands/CommandTest.swift (53%) rename tests/{integration => unit/_ST/Integration}/PackagistTest.swift (95%) rename tests/unit/{ => _ST}/Parsers/ValetConfigurationTest.swift (63%) diff --git a/PHP Monitor.xcodeproj/project.pbxproj b/PHP Monitor.xcodeproj/project.pbxproj index 85545a9..c85ff16 100644 --- a/PHP Monitor.xcodeproj/project.pbxproj +++ b/PHP Monitor.xcodeproj/project.pbxproj @@ -34,6 +34,8 @@ 036C39102E5C8D42008DAEDF /* PackagistError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036C390E2E5C8D3B008DAEDF /* PackagistError.swift */; }; 036C39112E5C8D42008DAEDF /* PackagistError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036C390E2E5C8D3B008DAEDF /* PackagistError.swift */; }; 036C39122E5C8D42008DAEDF /* PackagistError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036C390E2E5C8D3B008DAEDF /* PackagistError.swift */; }; + 036C39142E5CB822008DAEDF /* TestBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036C39132E5CB820008DAEDF /* TestBundle.swift */; }; + 036C3A212E5CBBAA008DAEDF /* ValetConfigurationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F76275447F100D44ED0 /* ValetConfigurationTest.swift */; }; 03BFF5272E312C3D007F96FA /* Startup+Timers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BFF5262E312C39007F96FA /* Startup+Timers.swift */; }; 03BFF5282E312C3D007F96FA /* Startup+Timers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BFF5262E312C39007F96FA /* Startup+Timers.swift */; }; 03BFF5292E312C3D007F96FA /* Startup+Timers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BFF5262E312C39007F96FA /* Startup+Timers.swift */; }; @@ -691,7 +693,6 @@ C4AD38B228ECD9D300FA8D83 /* TestableFileSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AD38B128ECD9D300FA8D83 /* TestableFileSystem.swift */; }; C4AD38B328ECD9D300FA8D83 /* TestableFileSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AD38B128ECD9D300FA8D83 /* TestableFileSystem.swift */; }; C4AF9F72275445FF00D44ED0 /* valet-config.json in Resources */ = {isa = PBXBuildFile; fileRef = C4AF9F70275445FF00D44ED0 /* valet-config.json */; }; - C4AF9F78275447F100D44ED0 /* ValetConfigurationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F76275447F100D44ED0 /* ValetConfigurationTest.swift */; }; C4AF9F7A2754499000D44ED0 /* Valet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F792754499000D44ED0 /* Valet.swift */; }; C4AF9F7B2754499000D44ED0 /* Valet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F792754499000D44ED0 /* Valet.swift */; }; C4AF9F7D275454A900D44ED0 /* ValetVersionExtractorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F7C275454A900D44ED0 /* ValetVersionExtractorTest.swift */; }; @@ -953,6 +954,7 @@ 036C39072E5C88A2008DAEDF /* PackagistTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PackagistTest.swift; sourceTree = ""; }; 036C39092E5C8CBD008DAEDF /* PackagistP2Response.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PackagistP2Response.swift; sourceTree = ""; }; 036C390E2E5C8D3B008DAEDF /* PackagistError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PackagistError.swift; sourceTree = ""; }; + 036C39132E5CB820008DAEDF /* TestBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestBundle.swift; sourceTree = ""; }; 03BFF5262E312C39007F96FA /* Startup+Timers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Startup+Timers.swift"; sourceTree = ""; }; 03BFF52B2E313240007F96FA /* StatusMenu+Driver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StatusMenu+Driver.swift"; sourceTree = ""; }; 03CC1FE42E3D220F0050FC18 /* InstallHomebrew.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstallHomebrew.swift; sourceTree = ""; }; @@ -1302,12 +1304,30 @@ path = Packagist; sourceTree = ""; }; - 036C39062E5C8890008DAEDF /* integration */ = { + 036C39062E5C8890008DAEDF /* Integration */ = { isa = PBXGroup; children = ( 036C39072E5C88A2008DAEDF /* PackagistTest.swift */, ); - path = integration; + path = Integration; + sourceTree = ""; + }; + 036C3A222E5CBC33008DAEDF /* _ST */ = { + isa = PBXGroup; + children = ( + C4C1019927C65A4D001FACC2 /* Commands */, + 036C3A232E5CBC57008DAEDF /* Parsers */, + 036C39062E5C8890008DAEDF /* Integration */, + ); + path = _ST; + sourceTree = ""; + }; + 036C3A232E5CBC57008DAEDF /* Parsers */ = { + isa = PBXGroup; + children = ( + C4AF9F76275447F100D44ED0 /* ValetConfigurationTest.swift */, + ); + path = Parsers; sourceTree = ""; }; 03BFF1D12E3CF4F2004C56A9 /* Provision */ = { @@ -1879,7 +1899,6 @@ C4F7807A25D7F84B000DBC97 /* unit */, C471E7AE28F9B4940021E251 /* feature */, C471E7BD28F9B90F0021E251 /* ui */, - 036C39062E5C8890008DAEDF /* integration */, ); path = tests; sourceTree = ""; @@ -2104,7 +2123,6 @@ isa = PBXGroup; children = ( C456A0D02AA6175D0080144F /* Config */, - C4AF9F76275447F100D44ED0 /* ValetConfigurationTest.swift */, C4F780AD25D80B37000DBC97 /* PhpExtensionTest.swift */, C43A8A2325D9D20D00591B77 /* HomebrewPackageTest.swift */, C42CFB1927DFE8BD00862737 /* NginxConfigurationTest.swift */, @@ -2198,6 +2216,7 @@ children = ( C4E2E86328FC2F1B003B070C /* XCPMApplication.swift */, C40F505428ECA64E004AD45B /* TestableConfigurations.swift */, + 036C39132E5CB820008DAEDF /* TestBundle.swift */, C43A8A1925D9CD1000591B77 /* Utility.swift */, ); path = Shared; @@ -2255,9 +2274,9 @@ C4F7807A25D7F84B000DBC97 /* unit */ = { isa = PBXGroup; children = ( + 036C3A222E5CBC33008DAEDF /* _ST */, C471E6D928F9AFC20021E251 /* Testables */, C40C7F1C27720E1400DDDCDC /* Test Files */, - C4C1019927C65A4D001FACC2 /* Commands */, C4C1019827C65A1A001FACC2 /* Versions */, C4C1019727C65A11001FACC2 /* Parsers */, ); @@ -3268,6 +3287,7 @@ C485707728BF455300539B36 /* HeaderView.swift in Sources */, C4F780B125D80B4D000DBC97 /* PhpExtension.swift in Sources */, C4D5CFCB27E0F9CD00035329 /* NginxConfigurationFile.swift in Sources */, + 036C39142E5CB822008DAEDF /* TestBundle.swift in Sources */, C4E6840A2AF26B830023ED25 /* BrewTapFormulae.swift in Sources */, C4068CA827B07A1300544CD5 /* SelectPreferenceView.swift in Sources */, C4F780CE25D80B75000DBC97 /* LocalNotification.swift in Sources */, @@ -3351,7 +3371,6 @@ C40FE738282ABA4F00A302C2 /* AppVersion.swift in Sources */, C415D3E92770F692005EF286 /* AppDelegate+InterApp.swift in Sources */, C4E49DEE28F764A00026AC4E /* TestableCommand.swift in Sources */, - C4AF9F78275447F100D44ED0 /* ValetConfigurationTest.swift in Sources */, C4611E612AEAD3110010BE24 /* ByteLimitView.swift in Sources */, C40175B92903108900763A68 /* ValetInteractor.swift in Sources */, C4CE3BBC27B324250086CA49 /* ComposerWindow.swift in Sources */, @@ -3432,6 +3451,7 @@ C485707628BF455100539B36 /* SectionHeaderView.swift in Sources */, C46EBC4828DB9644007ACC74 /* RealShell.swift in Sources */, C456A0CC2AA6166F0080144F /* BytePhpPreference.swift in Sources */, + 036C3A212E5CBBAA008DAEDF /* ValetConfigurationTest.swift in Sources */, C48DDD0E29C75C9E00D032D9 /* BlockingOverlayView.swift in Sources */, C4E4404727C56F4700D225E1 /* ValetSite.swift in Sources */, C44CCD4A27AFF3BC00CE40E5 /* MainMenu+Async.swift in Sources */, diff --git a/tests/Shared/TestBundle.swift b/tests/Shared/TestBundle.swift new file mode 100644 index 0000000..512fce0 --- /dev/null +++ b/tests/Shared/TestBundle.swift @@ -0,0 +1,50 @@ +// +// BundleHelper.swift +// PHP Monitor +// +// Created by Nico Verbruggen on 25/08/2025. +// Copyright © 2025 Nico Verbruggen. All rights reserved. +// + +import Foundation + +/** + This file is used to access bundle resources via test structs + that cannot access the bundle via the previous class syntax. + + After converting a test to Swift Testing, this is no longer possible: + + ```swift + class MyTest: XCTestCase { + static var configurationFileUrl: URL { + return Bundle(for: Self.self).url( + forResource: "valet-config", + withExtension: "json" + )! + } + } + ``` + + Normally, we would be able to access the bundle via the class + itself, but we'd prefer _not_ to make this accessible to other + classes. Thankfully, this is where `fileprivate` shines. + + The bundle is now accessed via `TestBundleClass`, which is not + accessible outside the scope of this file. `TestBundle` as a + global variable, though, is! + + Usage: + + ```swift + return TestBundle.url( + forResource: "valet-config", + withExtension: "json" + )! + ``` + */ + +fileprivate class TestBundleClass {} + +public var TestBundle: Bundle { + return Bundle(for: TestBundleClass.self) +} diff --git a/tests/unit/Commands/CommandTest.swift b/tests/unit/_ST/Commands/CommandTest.swift similarity index 53% rename from tests/unit/Commands/CommandTest.swift rename to tests/unit/_ST/Commands/CommandTest.swift index ed6fe2e..90e6f2d 100644 --- a/tests/unit/Commands/CommandTest.swift +++ b/tests/unit/_ST/Commands/CommandTest.swift @@ -6,21 +6,23 @@ // Copyright © 2023 Nico Verbruggen. All rights reserved. // -import XCTest +import Testing -class CommandTest: XCTestCase { +@Suite("Commands") +struct CommandTest { - func test_determine_php_version() { + @Test + func determinePhpVersion() { let version = Command.execute( path: Paths.php, arguments: ["-v"], trimNewlines: false ) - XCTAssert(version.contains("(cli)")) - XCTAssert(version.contains("NTS")) - XCTAssert(version.contains("built")) - XCTAssert(version.contains("Zend")) + #expect(version.contains("(cli)")) + #expect(version.contains("NTS")) + #expect(version.contains("built")) + #expect(version.contains("Zend")) } } diff --git a/tests/integration/PackagistTest.swift b/tests/unit/_ST/Integration/PackagistTest.swift similarity index 95% rename from tests/integration/PackagistTest.swift rename to tests/unit/_ST/Integration/PackagistTest.swift index 0d7b578..87e657d 100644 --- a/tests/integration/PackagistTest.swift +++ b/tests/unit/_ST/Integration/PackagistTest.swift @@ -8,6 +8,7 @@ import Testing +@Suite("Integration") struct PackagistTest { @Test func packagistRetrieval() async { let packageToCheck = "laravel/valet" diff --git a/tests/unit/Parsers/ValetConfigurationTest.swift b/tests/unit/_ST/Parsers/ValetConfigurationTest.swift similarity index 63% rename from tests/unit/Parsers/ValetConfigurationTest.swift rename to tests/unit/_ST/Parsers/ValetConfigurationTest.swift index 1c08b72..c4168e3 100644 --- a/tests/unit/Parsers/ValetConfigurationTest.swift +++ b/tests/unit/_ST/Parsers/ValetConfigurationTest.swift @@ -6,18 +6,20 @@ // Copyright © 2023 Nico Verbruggen. All rights reserved. // -import XCTest - -class ValetConfigurationTest: XCTestCase { +import Testing +import Foundation +@Suite("Parsers") +struct ValetConfigurationTest { static var jsonConfigFileUrl: URL { - return Bundle(for: Self.self).url( + return TestBundle.url( forResource: "valet-config", withExtension: "json" )! } - func test_can_load_config_file() throws { + @Test("Can load config file") + func can_load_config_file() throws { let json = try? String( contentsOf: Self.jsonConfigFileUrl, encoding: .utf8 @@ -27,13 +29,13 @@ class ValetConfigurationTest: XCTestCase { from: json!.data(using: .utf8)! ) - XCTAssertEqual(config.tld, "test") - XCTAssertEqual(config.paths, [ + #expect(config.tld == "test") + #expect(config.paths == [ "/Users/username/.config/valet/Sites", "/Users/username/Sites" ]) - XCTAssertEqual(config.defaultSite, "/Users/username/default-site") - XCTAssertEqual(config.loopback, "127.0.0.1") + #expect(config.defaultSite == "/Users/username/default-site") + #expect(config.loopback == "127.0.0.1") } }