Assertions and Unit Testing
这一章主要介绍Scala的断言以及Unit Test
使用断言有两种方式:
使用assert(condition, explanation)方法
使用ensuring()方法
Scala不仅有自己自带的测试框架,比如说:ScalaTest、specs、ScalaCheck,还支持直接使用Java的测试框架,如:JUnit、TestNG
在ScalaTest框架中,最简单的方法就是 extends org.scalatest.Suite。使用Suite需要使用 execute()方法,还有一种方法就是使用a trait called FunSuite,因为FunSuite覆盖了execute方法,所以我们可以 define tests as functions values rather than methods
使用 triple-equator 可以在测试失败时提供较为详细的失败信息,利用intercept方法可以测试是否正确的抛出异常
JUnit3Suite使得我们可以use ScalaTest’s assertion syntax。 JUnit3Suite既可以与JUnit一起使用,还可以与ScalaTest runner一起使用
ScalaTest提供了JUnit3WrapperSuite – enables us to run existing JUnit tests written in Java with ScalaTest’s runner;同样地,还提供了TestNGWrapperSuite – enables us to run existing TestNG tests written in Java with ScalaTest
Spec框架提供了“describers”以及”specifiers“,提供了specifications功能
ScalaCheck提供了 Property-based testing功能
基本上每种框架都有提供some mechanism for organizing and running tests,这里只以ScalaTest为例 – When a Suite is executed, it will execute its nest Suites as well as its tests. The nested Suite will in turn execute their nested Suites, and so on.
Case Classes and Pattern Matching
这一章主要介绍 case classes 以及 pattern matching。pattern matching属于函数式编程的内容,而Case classes则是 Scala’s way to allow pattern matching on objects without requiring a large amount of boilerplate.
在类的定义前加入case关键字,那么这个类就会成为 case class,使用case可以给class带来一些 syntactic convenience:
a. It adds a factory method with the name of the class. 这样就不用再使用new关键字构建新的实例了,而是可以直接使用类名构造
b. The second syntactic convenience is that all arguments in the parameter list of a case class implicitly get a val prefix, so they are maintained as fields.
c. Third, the compiler adds “natural” implementations of methods toString, hashCode, and equals to your class, then you can print, hash, and compare a whole tree consisting of the class and (recursively) all its arguments.
pattern matching有点类似于java的switch语句,除了格式之外,还有几处不同:
First, match is an expression in Scala, i.e., it always results in a value
Scala’s alternative expressions never “fall through” into the next case.
Third, if none of the patterns match, an exception named MatchError is thrown
Kinds of patterns
Pattern | 作用 |
---|---|
Wildcard patterns | 匹配任意的模式,不做绑定 |
Constant patterns | 匹配常量 |
Variable patterns | 匹配任意的模式,但是会将变量名绑定匹配的object上 |
Constructor patterns | 允许构造新的class,匹配对应的case class |
Sequence patterns | 允许匹配Seqs,如List,Array |
Tuple patterns | 允许匹配Tuple |
Typed patterns | 允许类型测试和转换 |
Scala对于变量还是常量有一个简单的分辨规则: a simple name starting with a lowercase letter is taken to be a pattern variable; all other references are taken to be constants. 当然,如果你想用小写字母表示常量,那么可以使用 ` ` 符号,这样的话Scala就会用相应的值来代替这个变量,形成一个常量(` ` 在Scala另外一个作用,可以命令与关键字相同的变量名,类似MySQL那样,如: writing Thread.
yield
() treats as an identifier rather than a key word)Scala uses the erasure model of generics, which means that no information about type arguments is maintained at runtime.唯一的另外就是数组,数组在运行时还是会保存它的类型信息
Variable binding没怎么看懂?这是什么意思呢? if the pattern succeeds, set the variable to the matched object just as with a simple variable pattern. 那这个和variable pattern有什么区别呢?
pattern guard给 pattern matching添加了额外的限制。A pattern guard comes after a pattern and starts with an if. The guard can be an arbitrary boolean expression, which typically refers to variables in the pattern. If a pattern guard is present, the match succeeds only if the guard evaluates to true.
pattern overlaps要求 the catch-all cases come after the more specific simplification rules. Because patterns are tried in the order in which they are written.
有时做模式匹配时,不知道到底有多少模式需要匹配。这时,我们可以利用关键字 sealed,sealed关键字能限制可创建的case class: A sealed class cannot have any new subclasses added except the ones in the same file. 使用 sealed关键字,那么编译器会把你检查,当你漏了匹配某个模式时,就会提示警告。当然,你也可以只匹配特定的模式,即使用关键字 @unchecked
Option type有两种形式: It can be of the form Some(x) where x is the actual value. Or it can be the None object, which represents a missing value. Option value通常来自对 collection 的操作。利用Option type 以及 pattern matching,就不用像Java那样再进行 NULL判断
事实上,Scala很多地方都用到了 pattern matching,如提取Tuple中的值、提取复杂表达式中的值等。 Case sequences as partial functions到时没怎么看懂
另外,书中还提到了extractor的概念,可以在类中隐藏 pattern matching的接口。不过,这个要看到后面才能够详细了解了。
我跳过了 A larger example 这一节,不过可以看出 pattern matching是一个非常强有力的工具,还是需要多写一些代码来详细体会一下 pattern matching 的魅力