         }
 
         return dict
+    }
+}
+
+extension Scheme.Test.CoverageTarget: JSONObjectConvertible {
+
+    public init(jsonDictionary: JSONDictionary) throws {
+        target = try jsonDictionary.json(atKeyPath: "target")
+        externalProject = jsonDictionary.json(atKeyPath: "externalProject")
+    }
+}
+
+extension Scheme.Test.CoverageTarget: JSONEncodable {
+    public func toJSONValue() -> Any {
+        guard let externalProject = externalProject else { return target }
+        return [
+            "target": target,
+            "externalProject": externalProject
+        ]
     }
 }
 


        public var config: String?
        public var gatherCoverageData: Bool
        public var disableMainThreadChecker: Bool
        public var commandLineArguments: [String: Bool]
        public var targets: [TestTarget]

    public init(jsonDictionary: JSONDictionary) throws {
        config = jsonDictionary.json(atKeyPath: "config")
        gatherCoverageData = jsonDictionary.json(atKeyPath: "gatherCoverageData") ?? Scheme.Test.gatherCoverageDataDefault
        coverageTargets = jsonDictionary.json(atKeyPath: "coverageTargets") ?? []
        disableMainThreadChecker = jsonDictionary.json(atKeyPath: "disableMainThreadChecker") ?? Scheme.Test.disableMainThreadCheckerDefault
        commandLineArguments = jsonDictionary.json(atKeyPath: "commandLineArguments") ?? [:]
        if let targets = jsonDictionary["targets"] as? [Any] {
