51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 1544|回复: 0
打印 上一主题 下一主题

[转贴] ScalaInAction测试——静态测试

[复制链接]
  • TA的每日心情
    擦汗
    3 天前
  • 签到天数: 527 天

    连续签到: 4 天

    [LV.9]测试副司令

    跳转到指定楼层
    1#
    发表于 2019-1-8 14:57:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    前言

    首先,我们需要了解如何测试发送和接受消息,包括发送然后不管的模式以及发送之后等待回复的交互式模式。
    使用的是 Scala 的测试框架 [ScalaTest]。这个框架被设计成可读性性很高。
    使用这个工具可以生成可读性很强的测试报告。当然 Akka 也为我们提供了测试工具 akka-test,如果没有这个工具,
    我们将面临相比与正常对象更加困难的测试环境。主要有下面四个原因:

    • 无法准确把握消息到达时间,因为消息是异步发送的
    • 并发,Actors 之间是并发多线程的,需要考虑更多的问题,如锁、障碍等
    • 无状态 Actor是无法直接访问对象的,只能通过 ActorRef
    • 集成测试。如果需要集成测试多个 Actor 就需要在它们直接做拦截,这也是不明确如何去实现的

    下面主要从两个方面演示如何利用 akka-testkit + ScalaTest 作测试:

    • Single threaded unit testing
    • Multi-threaded unit testing
    环境搭建

    安装 jdk + sbt + scala, build.sbt 中加入如下内容:

    1. name := "testdriven" #名字随意取,项目名称

    2. version := "0.1-SNAPSHOT"

    3. organization := "com.manning" #公司域名倒过来写,最后可以加入部门简称

    4. scalaVersion := "2.11.7"

    5. libraryDependencies ++= {
    6.   val akkaVersion       = "2.3.12"
    7.   Seq(
    8.     "com.typesafe.akka"       %%  "akka-actor"   % akkaVersion, #注意两个 %% 号的用法基本类
    9.     "com.typesafe.akka"       %%  "akka-slf4j"   % akkaVersion, #日志类
    10.     "com.typesafe.akka"       %%  "akka-testkit" % akkaVersion   % "test", #最后一个 %指定使用范围
    11.     "org.scalatest"           %%  "scalatest"    % "2.2.4"       % "test"
    12.   )
    13. }
    复制代码
    静态测试示例1
    1. package packagename
    2. import org.scalatest.WordSpecLike
    3. import org.scalatest.MustMatchers
    4. import akka.testkit.{ TestActorRef, TestKit }
    5. import akka.actor._

    6. package silenttest {

    7. class SilentActorTest extends TestKit(ActorSystem("testsystem"))
    8.     with WordSpecLike
    9.     with MustMatchers
    10.     with StopSystemAfterAll {

    11.     "A Silent Actor" must {

    12.       "change internal state when it receives a message, single" in {
    13.         import SilentActor._

    14.         //  利用TestActorRef 直接生成可以访问实际 Actor 对象的 Actor
    15.         val silentActor = TestActorRef[SilentActor]
    16.         silentActor ! SilentMessage("whisper")
    17.         //  静态的测试方法,直接访问actor的内部对象
    18.         silentActor.underlyingActor.state must (contain("whisper"))
    19.       }
    20.       //<end id="ch02-silentactor-test02"/>
    21.     }
    22.   }


    23.   object SilentActor {
    24.     case class SilentMessage(data: String)
    25.     case class GetState(receiver: ActorRef)
    26.   }

    27.   class SilentActor extends Actor {
    28.     import SilentActor._
    29.     var internalState = Vector[String]()

    30.     def receive = {
    31.       case SilentMessage(data) =>
    32.         internalState = internalState :+ data
    33.     }

    34.     def state = internalState
    35.   }
    36. }

    37. //通用类,目的是及时关闭所有Actor
    38. package common {
    39.   import akka.testkit.TestKit
    40.   import org.scalatest.{Suite, BeforeAndAfterAll}

    41.   trait StopSystemAfterAll extends BeforeAndAfterAll{

    42.     //注意这种混入手法
    43.     this: TestKit with Suite =>
    44.     override protected def afterAll(): Unit = {
    45.       super.afterAll()
    46.       system.shutdown()
    47.     }
    48.   }
    49. }
    复制代码
    静态测试示例2
    1. package silentactor03 {

    2.   class SilentActorTest extends TestKit(ActorSystem("testsystem"))
    3.     with WordSpecLike
    4.     with MustMatchers
    5.     with StopSystemAfterAll {

    6.     "A Silent Actor" must {

    7.       "change internal state when it receives a message, multi" in {
    8.         import SilentActor._

    9.         val silentActor = system.actorOf(Props[SilentActor], "s3")
    10.         silentActor ! SilentMessage("whisper1")
    11.         silentActor ! SilentMessage("whisper2")
    12.         //通过发送消息获取内部状态
    13.         silentActor ! GetState(testActor)
    14.         expectMsg(Vector("whisper1", "whisper2"))
    15.       }

    16.     }

    17.   }


    18.   object SilentActor {
    19.     case class SilentMessage(data: String)
    20.     case class GetState(receiver: ActorRef)
    21.   }

    22.   class SilentActor extends Actor {
    23.     import SilentActor._
    24.     var internalState = Vector[String]()

    25.     def receive = {
    26.       case SilentMessage(data) =>
    27.         internalState = internalState :+ data
    28.       case GetState(receiver) => receiver ! internalState
    29.     }
    30.   }
    31. }
    复制代码



    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-18 06:20 , Processed in 0.062673 second(s), 24 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表