如何对特定于语言环境的本地通知进行单元测试

How to Unit Test locale-specific local notifications

我刚刚在我的应用程序中添加了本地通知。如果应用程序区域设置的 regionCode(即 Locale.current.regionCode)是 "US" 或 "CA",这些通知应该 触发。我对语言环境的language感兴趣。

我也会想写补充测试用例,但是一旦我知道如何写一个测试用例,另一个自然就会跟着写。

因此,我的问题是:如何将 Locale 注入测试(参见 testSuccessfulNotificationDelivery())?

LocalNotificationTests.swift:

class LocalNotificationTests: XCTestCase {

    let notification1 = LocalNotification(toTriggerInSeconds: 5)
    let notification2 = LocalNotification(toTriggerInSeconds: 6)

    // This object manages LocalNotifications 
    // by building them into UNUserNotifications
    // and then scheduling them using UNUserNotificationCenter.
    let notificationManager = NotificationManager()

    func testSuccessfulNotificationDelivery() {

        // setup locale and use it for testing, somehow
        let  = Locale(identifier: "en_CA")

        // The answer to my question would go here. 
        // (Inject Locale into the test, somehow?)

        notificationManager.schedule(notifications: [notification1, notification2], 
                                     withRegionCode: .regionCode)

        let expectation = self.expectation(description: "notification delivery")

        var deliveredNotifications: [UNNotification]?

        UNUserNotificationCenter.current().getDeliveredNotifications {
            deliveredNotifications = [=10=]
            expectation.fulfill()
        }

        waitForExpectations(timeout: 10, handler: nil)

        XCTAssertEqual(deliveredNotifications?.count, 2) 
    }
}

假设默认 setup()tearDown()

它不能完全满足您的需求,但您可以检查一下post

这似乎是关于在测试用例中更改位置样式的重要说明。

Once we have executed test in simulator or device it can carry the same language and locale to the next XCUI test case. There is no way to clear the simulator content in between the test cases so it’s good idea to create new scheme for each country and locale

你也可以检查Apple Documentation

如果您编辑您的方案并select Test/Options,您可以设置应用区域:
手动测试有不同的方案就够了吗?

此外,如果您创建一个机器人,您可以设置构建配置,使其 select 属于某个区域: 如果您定义不同的机器人,您可以 运行自动测试。

我不确定你是否可以用 "XCTest" 做到这一点,但我相信你可以用 "XCUITest" 做到这一点。你大概可以这样做吗?

class CALocalNotificationTests: LocalNotificationTests {
    override func setUp() {
        super.setUp()

        let app = XCUIApplication()
        app.launchArguments = ["-AppleLocale", "en_CA"]
        app.launch()
    }

    func testSuccessfulNotificationDelivery() {
        testSuccessfulNotificationDelivery(with: Locale(identifier: "en_CA"))
    }
}

class LocalNotificationTests: XCTestCase {

    let notification1 = LocalNotification(toTriggerInSeconds: 5)
    let notification2 = LocalNotification(toTriggerInSeconds: 6)
//
//    // This object manages LocalNotifications
//    // by building them into UNUserNotifications
//    // and then scheduling them using UNUserNotificationCenter.
    let notificationManager = NotificationManager()

    func testSuccessfulNotificationDelivery(with locale: Locale) {

        notificationManager.schedule(notifications: [notification1, notification2],
                                     withRegionCode: locale.regionCode)

        let expectation = self.expectation(description: "notification delivery")

        var deliveredNotifications: [UNNotification]?

        UNUserNotificationCenter.current().getDeliveredNotifications {
            deliveredNotifications = [=10=]
            expectation.fulfill()
        }

        waitForExpectations(timeout: 10, handler: nil)

        XCTAssertEqual(deliveredNotifications?.count, 2)
    }
}

我认为这很琐碎,但 app.launchArguments = ["-AppleLocale", "en_CA"] 是关键。

您可以为不同的语言环境创建不同的测试(子)类。

class LocalNotificationTests: XCTestCase {

let notification1 = LocalNotification(toTriggerInSeconds: 5)
let notification2 = LocalNotification(toTriggerInSeconds: 6)

// This object manages LocalNotifications 
// by building them into UNUserNotifications
// and then scheduling them using UNUserNotificationCenter.
let notificationManager = NotificationManager()

func testSuccessfulCanadaNotificationDelivery() {
    let canadaLocale = Locale("en_CA")
    XCTAssertTrue(notificationDelivered(with: canadaLocale))
}

func testNotificationDeliveryFailure() {
    let notCanadaOrUs = Locale("ru_RU")
    XCTAssertFalse(notificationDelivered(with: notCanadaOrUs))
}


private func notificationDelivered(with locale: Locale) -> Bool {

    // The answer to my question would go here. 
    // (Inject Locale into the test, somehow?)

    notificationManager.schedule(notifications: [notification1, notification2], 
                                 withRegionCode: locale.regionCode)

    let expectation = self.expectation(description: "notification delivery")

    var deliveredNotifications: [UNNotification]?

    UNUserNotificationCenter.current().getDeliveredNotifications {
        deliveredNotifications = [=10=]
        expectation.fulfill()
    }

    waitForExpectations(timeout: 10, handler: nil)

    return (deliveredNotifications?.count ?? 0) == 2
}

你能做这样的事情吗?