Xcode 单元测试 - 添加一个用于所有测试类的通用函数
Posted
技术标签:
【中文标题】Xcode 单元测试 - 添加一个用于所有测试类的通用函数【英文标题】:Xcode Unit Testing - Add a common function to be used across all test classes 【发布时间】:2018-08-13 12:45:49 【问题描述】:我已经使用 Swift 为我的项目实施了单元测试。在测试用例中,我正在读取来自 CSV 文件的输入值并对其进行验证。目前,每当我创建新的测试用例类时,需要将读取 CSV 文件并解析它的所有函数复制并粘贴到新的测试类中。有没有办法使用这些函数在一个地方读取 CSV 文件,以便所有测试类都可以使用它们?我想重用的代码是:
func csv(data: String) -> [[String]]
var result: [[String]] = []
let rows = data.components(separatedBy: "\n")
for row in rows
let columns = row.components(separatedBy: ",")
result.append(columns)
return result
func cleanRows(file:String)->String
var cleanFile = file
cleanFile = cleanFile.replacingOccurrences(of: "\r", with: "\n")
cleanFile = cleanFile.replacingOccurrences(of: "\n\n", with: "\n")
return cleanFile
func readDataFromCSV(fileName:String, fileType: String)-> String!
let bundle = Bundle(for: type(of: self))
let path = bundle.path(forResource: fileName, ofType: fileType)!
do
let contents = try String(contentsOfFile: path, encoding: .utf8)
return contents
catch
print("File Read Error for file \(path)")
return nil
【问题讨论】:
你可以创建一个静态函数并在任何地方使用它,你试过这个流程吗? 不,我会试试的。我应该将静态函数保留在任何一个测试用例文件中吗? 我喜欢使用实用程序和扩展。您应该通过测试覆盖这些方法,然后您可以在任何地方重复使用它们。 让 bundle = Bundle(for: type(of: self)).创建静态函数时如何处理? 像任何其他测试一样。对于最简单的方法,使用规则:给定 -> 当 -> 然后。更多测试签到详情:https://www.raywenderlich.com/709-ios-unit-testing-and-ui-testing-tutorial
【参考方案1】:
您可以使用 Helper 文件来处理此问题。您可以使用静态函数和扩展来完成此操作。
首先,向您的测试项目添加一个新的 swift 文件,最好命名为描述性的,在这种情况下CSVTestUtility
或CSVTestHelper
是合理的。
接下来我们要创建一个包含这些方法的结构体。
struct CSVTestUtility
static func csv(data: String) -> [[String]]
var result: [[String]] = []
let rows = data.components(separatedBy: "\n")
for row in rows
let columns = row.components(separatedBy: ",")
result.append(columns)
return result
static func cleanRows(file:String)->String
var cleanFile = file
cleanFile = cleanFile.replacingOccurrences(of: "\r", with: "\n")
cleanFile = cleanFile.replacingOccurrences(of: "\n\n", with: "\n")
return cleanFile
static func readDataFromCSV(fileName:String, fileType: String)-> String!
let bundle = Bundle(for: type(of: self) as! AnyClass)
let path = bundle.path(forResource: fileName, ofType: fileType)!
do
let contents = try String(contentsOfFile: path, encoding: .utf8)
return contents
catch
print("File Read Error for file \(path)")
return nil
此时我们要确保将文件添加到单元测试项目中,因此请确保在文件上为测试项目设置目标成员资格。一旦完成,我们就可以通过静态结构调用来调用这些方法。
需要注意的一点是,Bundle init 可能会根据您的调用方式提供一些意想不到的功能。如果您计划在测试用例之外测试其他包,则可能需要对其进行更改。
还有一点值得注意的是,其中两个方法接受字符串输入,因此可以将它们重构为字符串扩展。
extension String
func csv() -> [[String]]
var result: [[String]] = []
let rows = self.components(separatedBy: "\n")
for row in rows
let columns = row.components(separatedBy: ",")
result.append(columns)
return result
func cleanRows()->String
var cleanFile = self
cleanFile = cleanFile.replacingOccurrences(of: "\r", with: "\n")
cleanFile = cleanFile.replacingOccurrences(of: "\n\n", with: "\n")
return cleanFile
因此,如果您将上述扩展名放入新的 CSVTestUtility 文件中,您将能够直接从您正在使用的字符串中访问方法,例如:
var csvData = "somedata"
var csvConvertedData = csvData.csv()
for row in csvConvertedData
row.cleanRows()
如您所见,帮助程序和实用程序是帮助单元测试共享通用功能的宝贵工具,但与往常一样,请确保您的工作易于识别,这样您就可以了解未来的意图是什么对项目新鲜。
【讨论】:
let bundle = Bundle(for: type(of: self)) 是我在这里找到的问题。它显示错误“无法将'CSVTestUtility.Type.Type'类型的值转换为预期的参数类型'AnyClass'(又名'AnyObject.Type')” 解决了 Bundle 的问题。它还致力于将 CSVTestUtility 从 Struct 更改为 Class。 您可以这样做,也可以使用type(of: self) as! AnyClass
将调用投射到 AnyClass。两者都可以。以上是关于Xcode 单元测试 - 添加一个用于所有测试类的通用函数的主要内容,如果未能解决你的问题,请参考以下文章