danger / swift

⚠️ Stop saying "you forgot to …" in code review

Home Page:https://danger.systems/swift/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

DangerDSL mocking [IDEA]

Nikoloutsos opened this issue · comments

Hi, first of all thanks for this danger-js wrapper it is so cool 🎉.
I do have an idea that I'd like to hear your opinion about:

As I was developing a danger plugin I wanted to make it fully-testable. For doing that I had to mock DangerDSL which I spent a lot of time and the only way I found was initialising through JSON files. So if i have 200 tests I should have 200 JSONs (1000 lines each) . So i came up with this idea 👇

Proposal

We can make use of Runtime library https://github.com/wickwirew/Runtime that will allow us to change let properties of dangerDSL😆.
At this point in my repo I have implemented this and working well.

/// Gives the ability  to a struct/class to modify properties even let through runtime mirroring
protocol RuntimeModifiable {
    /// Use this method to change a property on your RuntimeModifiable
    /// ```swift
    /// // In case you want to pass nil!
    /// try mutablePR.rchange(property: "assignee", with: Optional<GitHub.User>.none)
    /// ```
    mutating func rchange(property: String, with value: Any) throws
}

extension RuntimeModifiable {
    mutating func rchange(property: String, with value: Any) throws {
        let info = try typeInfo(of: type(of: self))
        let property = try info.property(named: property)
        try property.set(value: value, on: &self)
    }
}

// MARK: DangerDSL struct
extension GitHub.PullRequest: RuntimeModifiable {}
extension GitHub: RuntimeModifiable {}
extension DangerDSL: RuntimeModifiable {}
extension GitHub.User: RuntimeModifiable {}
...

and test now looks like this (in this test we make dangerDSL to have an assignee):

func testAssigneeExist() throws {
        // Given
        var fixture = githubWithFilesDSL()
        var mutableGithub = fixture.github!
        var mutablePR = fixture.github.pullRequest
        
        try mutablePR.rchange(property: "assignees", with: [GitHub.User(id: 0, login: "", userType: .user)])
        try mutableGithub.rchange(property: "pullRequest", with: mutablePR)
        try fixture.rchange(property: "github", with: mutableGithub)
        
        let sut = AssigneeExistsStep(danger: fixture)
        // When
        sut.execute()

        // Then
        XCTAssertTrue(sut.status.isSuccess)
    }

By doing this we can stub what we want in dangerDSL in contrast of bombarding the whole package with JSON files.
Maybe this idea can be a seperate package (danger plugin) that can be used for easier DangerDSL mocking.

What do you think?

Hey @Nikoloutsos, thank you for putting this proposal together :)
We already have something similar to allow you to modify the DangerDSL:
Look for example this test file, where the created files are modified from the DSL in the test https://github.com/f-meloni/danger-swift-coverage/blob/master/Tests/DangerSwiftCoverageTests/CoverageTests.swift.
This only allows you to modify the created/modified/deleted files, and allows you to create a fileMap to stub also the content of the file when you go to read it with danger.utils, so is a lot simpler than what you suggest, and would be cool to have something more complex :).

We have https://github.com/danger/swift/tree/master/Sources/DangerFixtures that is already a testing lib, and I would be happy to see something like the code you suggest, or something like a builder there, that can then help the creators of Danger plugins :)