使用TDD构建JSON解析器
最近,一个朋友需要解析具有自定义格式的文件,并问我如何实现该文件。 我的脑海立刻被我上大学的记忆所淹没。 因此,我回答了他,我首先将制作一个词法分析器,该词法分析器将使用文本文件并生成令牌,然后创建一个状态机,该状态机会将令牌作为状态转换的事件,并且每个转换都会建立一点点解析的结果,直到达到终端状态为止。
我对TDD感兴趣已经有一段时间了,但是没有机会尝试一下,因此这看起来像是一个制作东西的好机会。
在本系列文章中,我将尝试使用TDD创建JSON解析器,并尝试在每个步骤中共享我的尽管流程。 让我们一起学习🙂
在我们开始之前,有一些想法:
- 我将生产代码和测试代码都写在一个文件中,以便于在它们之间进行切换。
- 我们将从仅解析没有空格和换行符的JSON文件开始。 我们稍后会处理。
- 我知道Foundation库有一个非常优化的JSON解析库,我们在Swift 4中添加了Codable协议,涵盖了JSON解析,但是我主要是作为练习来做的。
- 对于那些不熟悉的人,我将尝试遵循TDD的三个规则:
除非要通过失败的单元测试,否则不允许编写任何生产代码。
您不能编写任何足以使单元测试失败的单元测试。 而编译失败就是失败。
您不能编写任何足以通过一项失败的单元测试的生产代码。
我们首先创建带有单元测试的可可触摸框架项目,然后删除默认测试
对于最退化的情况,第一个测试应该始终是。 因为我们没有在任何地方传递可选参数,所以我们可以创建的最简陋的字符串是空字符串。 现在,我们只说如果解析失败,则返回nil。
现在我们处于红色阶段,我们必须通过此测试通过以使其再次变为绿色。 第一个错误是JSONParser不存在。 因此,我们创建了它。 让我们上一堂课。 现在,对parse方法的调用不存在。 我们可以通过创建一个接受字符串并返回Any的方法解析来解决此问题。 。 空字符串应该失败,因为它不是有效的JSON,因此我们只返回nil 。
在JSON RFC中,它表示JSON可以是以下之一: Boolean , Number , String , Array , Object 。 让我们从最简单的解析器开始:一个布尔值。
首先,我们将解决真实情况:
TDD通过最简单的方式产生更好的结果,因此让我们尝试最简单的方法来验证值是否为true 。
这次我们有机会在测试代码中进行一些重构 。 解析器分配开始重复,并且可能会在每个测试中重复。 将其移至设置功能似乎是个不错的机会。 然后我们有:
列表上的下一个是处理错误的布尔值。 我们以与真实案例相同的方式进行测试:
我们做了一个if来检查是否正确 。 让我们尝试使用相同的方法,并将if演化为switch语句。
我们该怎样改进这个? 我们需要一种将“ true”转换为true并将“ false”转换为false的方法 ,并且如果解析失败,我们不能忘记返回nil 。 等等,有一个功能可以做到这一点! 它叫做… Bool.init !
现在我们已经处理了布尔值,让我们转到另一种类型。 所有这些双引号和所有内容都使字符串看起来很复杂。 数组和对象看起来更糟。 让我们尝试一下数字。 JSON的数字定义适用于整数和浮点数,但让我们从int解析开始。
布尔事件过后,我们变得聪明起来。 整数将变得容易。 让我们使用Int.init并嘲笑失败的测试。
即使看起来不错,我也不喜欢在代码中到处都有if let和guard let。 也许我们可以简化一下。 Bool初始化程序返回一个可选的Bool。 我们只想在布尔初始化程序失败时调用Int初始化程序。 是否只有可选为nil时才调用的函数? 有! 而且它甚至是一个运算符 !
欢迎使用单行编码。 我们的解析器可以处理两种类型的JSON值,并且它是一行编写的! 现在,它得到了一系列测试的支持。 在我们最近的更改之后,哪个当然可以通过。
我们着火了! 到目前为止,这个小解析器给我带来了很多乐趣,而且我相信在完成之前,我还会有更多的乐趣。
最终代码可在GitHub上找到
每个TDD步骤都在单个提交中完成,因此您可以使用自己喜欢的git工具比较提交差异来跟踪进度。
- RCTBatchedBridge已弃用,将在未来的React Native版本中删除
- 无法滚动到XCode 5 Interface Builder中的长静态TableViewController的底部来编辑折叠下方的单元格
- 延迟applicationDidEnterBackground屏幕捕获
- 我如何只允许从我的iOS应用程序访问我的MySQL数据库? (使用webapp作为数据库的网关)
- Xamarin – 带有绝对布局的文本和图像的button导致错误alignment的元素
- 如何检查一个数字是否是NSInteger或浮点在IOS?
- 在IOS Xamarin Forms中更改切换颜色
- 如何将UIWebView的内容保存为图像
- 目标C中具有相同函数名称的类别