精华内容
下载资源
问答
  • js 正则匹配 小结

    2021-01-17 13:17:21
    JS的正则表达式rge.test(str) 检验目标对象中是否包含匹配模式,并相应的返回true或false rge.sourcestr.search(rge) 将返回一个整数值,指明这个匹配距离字符串开始的偏移位置。如果没有找到匹配,则返回 -1str....

    JS的正则表达式

    rge.test(str) 检验目标对象中是否包含匹配模式,并相应的返回true或false   rge.source

    str.search(rge) 将返回一个整数值,指明这个匹配距离字符串开始的偏移位置。如果没有找到匹配,则返回 -1

    str.replace(re, function(){}) 替换匹配到的数值

    rge.exec(str) 没有找到匹配,则它返回 null。如果它找到匹配,则 exec 方法返回一个数

    str.match(rge) 用正则表达式模式在字符串中运行查找,并返回包含该查找结果的一个数组(全文匹配模式g,否则只返回第

    一个匹配的内容)

    match 方法没有找到匹配,返回 null。如果找到匹配返回一个数组并且更新全局 RegExp 对象的属性以反映匹配结果

    Input 属性包含整个的被查找字符串。

    Index 属性包含了在整个被查找字符串中匹配的子字符串的位置。

    LastIndex

    属性包含了最后一次匹配中最后一个字符的下一个位置。

    function

    RegExpTest()

    {

    var ver = Number(ScriptEngineMajorVersion() + "."

    +

    ScriptEngineMinorVersion())

    if (ver >= 5.5){ // 测试 JScript

    的版本。

    var src = "The rain in Spain falls mainly in the

    plain.";

    var re = /\w+/g; //

    创建正则表达式模式。

    var

    arr;

    while ((arr = re.exec(src)) !=

    null)

    document.write(arr.index + "-" + arr.lastIndex +

    arr + "\t");

    }

    else{

    alert("请使用 JScript

    的更新版本");

    }

    }

    语法 1 re =

    /pattern/[flags]

    语法 2 re = new

    RegExp("pattern",["flags"])

    g (全文查找出现的所有

    pattern)

    i

    (忽略大小写)

    m (多行查找)

    定界符:/ /

    前导字符:

    元字符:规定前导字符在目标对象中出现的模式

    “+”元字符规定其前导字符必须在目标对象中连续出现一次或多次。 /fo+/

    “*”元字符规定其前导字符必须在目标对象中出现零次或连续多次。 /eg*/

    “?”元字符规定其前导对象必须在目标对象中连续出现零次或一次。 /Wil?/

    限定符:可以指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。 {n}

    n

    {n,}

    {n,m}

    \s:用于匹配单个空格符,包括tab键和换行符;

    \S:用于匹配除单个空格符之外的所有字符;

    \d:用于匹配从0到9的数字;[0-9]

    \D:用于匹配从0到9的数字;[^0-9]

    \w:用于匹配字母,数字或下划线字符;'[A-Za-z0-9_]'

    \W:用于匹配所有与\w不匹配的字符;'[^A-Za-z0-9_]'

    .

    :用于匹配除换行符之外的所有字符。

    \cx 匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。 x

    的值必须为 A-Z 或 a-z 之一。否

    则,将 c 视为一个原义的 'c'

    字符。

    \f 匹配一个换页符。等价于 \x0c 和

    \cL。

    \n 匹配一个换行符。等价于 \x0a 和

    \cJ。

    \r 匹配一个回车符。等价于 \x0d 和

    \cM。

    \s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [

    \f\n\r\t\v]。

    \S 匹配任何非空白字符。等价于 [^

    \f\n\r\t\v]。

    \t 匹配一个制表符。等价于 \x09 和

    \cI。

    \v 匹配一个垂直制表符。等价于 \x0b 和 \cK。

    定位符:规定匹配模式在目标对象中的出现位置。 较为常用的定位符包括: “^”, “$”, “\b” 以及

    “\B”。

    “^”定位符规定匹配模式必须出现在目标字符串的开头

    “$”定位符规定匹配模式必须出现在目标对象的结尾

    “\b”定位符规定匹配模式必须出现在目标字符串的开头或结尾的两个边界之一

    “\B”定位符则规定匹配对象必须位于目标字符串的开头和结尾两个边界之内,

    为了能够方便用户更加灵活的设定匹配模式,正则表达式允许使用者在匹配模式中指定某一个范围而不局限于具体的字符。

    例如:

    /([a-z][A-Z][0-9])+/ 上述正则表达式将会与任何由字母和数字组成的字符串,如 “aB0”

    等相匹配。

    “|”。例如:/to|too|2/ 上述正则表达式将会与目标对象中的 “to”, “too”, 或 “2” 相匹配。

    否定符 “[^]”。与我们前文所介绍的定位符 “^”

    不同,否定符 “[^]”规定目标对象中不能存在模式中所规

    的字符串。

    当“^”出现在

    “[]”内时就被视做否定运算符;而当“^”位于“[]”之外,或没有“[]”时,则应当被视做定

    符。

    ? 当该字符紧跟在任何一个其他限制符 (*, +, ?,

    {n}, {n,}, {n,m})

    后面时,匹配模式是非贪婪的。非贪婪模   式

    尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串

    "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有

    'o'。

    . 匹配除 "\n" 之外的任何单个字符。要匹配包括

    '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。

    优先级如下:

    1.\ 转义符

    2.(), (?:), (?=), []

    圆括号和方括号

    3.*, +, ?, {n}, {n,}, {n,m}

    限定符

    4.^, $, \anymetacharacter

    位置和顺序

    5.|“或”操作

    正则表达式

    "^\\d+$"  //非负整数(正整数 + 0)

    "^[0-9]*[1-9][0-9]*$"  //正整数

    "^((-\\d+)|(0+))$"  //非正整数(负整数 +

    0)

    "^-[0-9]*[1-9][0-9]*$"  //负整数

    "^-?\\d+$"    //整数

    "^\\d+(\\.\\d+)?$"  //非负浮点数(正浮点数 +

    0)

    "^(([0-9]+\\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\\.[0-9]+)|([0-9]*[1-9][0-9]*))$"

    //正浮点数

    "^((-\\d+(\\.\\d+)?)|(0+(\\.0+)?))$"  //非正浮点数(负浮点数

    + 0)

    "^(-(([0-9]+\\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\\.[0-9]+)|([0-9]*[1-9][0-9]*)))$"//负浮点数

    "^(-?\\d+)(\\.\\d+)?$"  //浮点数

    "^[A-Za-z]+$"  //由26个英文字母组成的字符串

    "^[A-Z]+$"  //由26个英文字母的大写组成的字符串

    "^[a-z]+$"  //由26个英文字母的小写组成的字符串

    "^[A-Za-z0-9]+$"  //由数字和26个英文字母组成的字符串

    "^\\w+$"  //由数字、26个英文字母或者下划线组成的字符串

    "^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$"    //email地址

    "^[a-zA-z]+://(\\w+(-\\w+)*)(\\.(\\w+(-\\w+)*))*(\\?\\S*)?$"  //url

    "^[A-Za-z0-9_]*$"

    /^\[ \t]*$/ "^\[ \t]*$"

    匹配一个空白行。

    /\d{2}-\d{5}/ "\d{2}-\d{5}" 验证一个ID

    号码是否由一个2位数字,一个连字符以及一个5位数字组成。

    /.*/

    ".*"

    匹配一个 HTML 标记。

    展开全文
  • 今天在运用小程序云开发实现删除点赞记录这个功能点的过程中,遇到一个问题:如何实现对象数组根据查询条件匹配删除 解决思路: 我们可以通过当前用户的openid这个条件来删除添加在数组prizelist里面一个数组对象...

    问题描述:

    今天在运用小程序云开发实现删除点赞记录这个功能点的过程中,遇到一个问题:如何实现对象数组根据查询条件匹配删除


    解决思路:

    我们可以通过当前用户的openid这个条件来删除添加在数组prizelist里面一个数组对象。用到的是微信官方文档的pull数组更新操作符,文档中对其的具体描述是:给定一个值或一个查询条件,将数组中所有匹配给定值或查询条件的元素都移除掉。小程序官方文档pull数组更新操作符

    删除点赞记录


    解决方案:

     //删除点赞记录
      mylike_deleteaction(e) {
        console.log(e)
        console.log(e.currentTarget.dataset.id)
        const db= wx.cloud.database()
        const _ = db.command
        db.collection('message').doc(e.currentTarget.dataset.id).update({
          data: {
             isPrize:false,
             //pull数组更新操作符
             prizelist:_.pull({
               //查询条件
               //当前用户的openid与删除对象prizelist的openid相同
               openid:_.eq(app.globalData.openid)
             })
          },
          success(res) {
            console.log(res)
            wx.showToast({
              title: '删除成功',
            })
          }
        })
      },
    
    展开全文
  • Jetpack 系列之AppSearch

    千次阅读 2021-06-18 23:15:14
    前言 在今年的Google I/O 大会上,Jetpack库新增了三个组件(刚发布Alpha版本),分别是MarcrobenChmark、AppSearch和Google Shortc

    前言

            在今年的Google I/O 大会上,Jetpack库新增了三个组件(刚发布Alpha版本),分别是MarcrobenChmarkAppSearchGoogle Shortcuts,MarcrobenChmark组件是用来衡量代码性能一个库,Google Shortcuts听起来像是一种快捷方式,本文我们将着重带领大家领略一下AppSearch的使用。那么什么是AppSearch呢?

    什么是AppSearch

            按照官方描述,AppSearch 是一个搜索库,用于管理本地存储的结构化数据,其中包含用于将数据编入索引和通过全文内搜索来检索数据的 API。您可以使用此库来为用户构建自定义的应用内搜索功能。看到应用内搜索,我首先想到了Android设置中的搜索页面,比如我们搜索显示两个字,这里将显示出所有包含“显示”字样的功能入口,如图1所示:

                                              

                                                                图1 设置内搜索

    接下来我们来详细看如何使用AppSearch以及我踩过的那些坑。

    引入相关库

    首先我们在build.gradle中引入AppSearch组件的相关库,代码如下所示:

    def appsearch_version = "1.0.0-alpha01"
    implementation("androidx.appsearch:appsearch:$appsearch_version")
    kapt("androidx.appsearch:appsearch-compiler:$appsearch_version")
    implementation("androidx.appsearch:appsearch-local-storage:$appsearch_version")

    在 AppSearch 中,一个数据单元被表示为一个文档。 AppSearch 数据库中的每个文档都由其命名空间和 ID 唯一标识。 命名空间用于将来自不同来源的数据分开,这一点相当于sql中的表。所以接下来我们来创建一个数据单元。

    创建一个数据单元

    我们以新闻类为例,创建的数据类如下所示:

    @Document
    data class News(
        @Document.Namespace
        val namespace: String,
        @Document.Id
        val id: String,
        @Document.StringProperty(indexingType = AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES)
        val newsTitle: String,
        @Document.StringProperty(indexingType = AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES)
        val newsContent: String
    )

    首先在AppSearch中所有的数据单元都要使用@Document注解,namespace和id在上面说了是数据类型的必须字段,newsTitle和newsContent是我们自己定义的新闻标题和新闻内容字段,这里提一下

    @Document.StringProperty(indexingType = AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES)

    这个注解,@Document.StringProperty 就是要将字符串类型的变量配置成AppSearch的属性,如果是整型那就是

    @Document.Int64Property

    布尔类型就是

    @Document.BooleanProperty

    等等等等,indexingType 属性值可以理解为匹配方式,这里设置为INDEXING_TYPE_PREFIXES,如当匹配条件是Huang的时候 可以匹配到HuangLinqing,其他属性感兴趣的可以看下源码androidx.appsearch.app.AppSearchSchema类。创建完数据类之后,同其他数据库操作一样,接下来来创建一个数据库。

    创建数据库

    创建数据库就会返回给我们一个ListenableFuture,用于整个数据库的操作,代码如下所示:

    val context: Context = applicationContext
    val sessionFuture = LocalStorage.createSearchSession(
        LocalStorage.SearchContext.Builder(context, /*databaseName=*/"news")
            .build()
    )

    此时我们可以看到这行代码报了一个错误,错误如下所示:

    大致意思是说还需要依赖一个库,说实话,其实AppSearch库完全可以自己依赖一下,这样对开发者方便很多,但是毕竟AppSearch刚出测试版,要求不能太高。

    我们在build.gradle中引入guava库,代码如下所示:
     

    implementation("com.google.guava:guava:30.1.1-android")

    依赖之后,上述代码就可以正常运行了,不过运行的话这里还不行,我们设置java1.8的环境才可以,否则后面运行会出现java.lang.NoSuchMethodError: No static method metafactory的错误

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    // For Kotlin projects
    kotlinOptions {
        jvmTarget = "1.8"
    }

    原问题我提给了Google,可参看https://issuetracker.google.com/issues/191389033

    设置数据模式

    AppSearch中有Schema 和schema types的概念,意思是模式和模式类型,模式由表示独特数据类型的模式类型组成这里指的就是News类,模式类型由包含名称、数据类型和基数的属性组成。这里设置数据模式,其实就是指定我们可以在这个名称为“news”的数据空中可以添加什么样类型的数据。

    val setChemaRequest = SetSchemaRequest
        .Builder()
        .addDocumentClasses(News::class.java).build()
    
    var setSchemaFuture = Futures.transformAsync(
        sessionFuture,
        AsyncFunction<AppSearchSession?, SetSchemaResponse?> {
            it?.setSchema(setChemaRequest)
        },
        mainExecutor
    )

    首先我们创建了一个数据类型为News类的模式类,然后通过AppSearchSession的setSchema方法为数据文档设置了数据模式,这里大家疑惑的地方可能是Futures.transformAsync这个方法,其实很简单,Future就是一个Java中的异步线程框架,可以类比为协程,所以说如果AppSearch的设计可以不依赖Future在使用上可能会简单许多。

    不过令我差异的是,我咨询了若干做Java的朋友,他们都表示,这个东西很少用。所以这里咱们只专注AppSearch的使用,Futures相关类的使用,感兴趣的可以深入学习下。

    设置好数据模式后,我们就可以写入数据了。

    写入数据

    我们首先定义一个要插入的数据类,如下所示:

    val new1 = News(
        namespace = "new1",
        id = "new_id_2",
        newsTitle = "who is a boy",
        newsContent = "Everyone, guess who is the handsome boy"
    )

    构建PutDocumentsRequest对象并执行

    val putRequest = PutDocumentsRequest.Builder().addDocuments(new1).build()
    val putFuture = Futures.transformAsync(
        sessionFuture,
        AsyncFunction<AppSearchSession?, AppSearchBatchResult<String, Void>?> {
            it?.put(putRequest)
        },
        mainExecutor
    )

    执行结果我们可以通过Futures.addCallback来监听,方法如下所示:

    Futures.addCallback(
        putFuture,
        object : FutureCallback<AppSearchBatchResult<String, Void>?> {
            override fun onSuccess(result: AppSearchBatchResult<String, Void>?) {
                // Gets map of successful results from Id to Void
                val successfulResults = result?.successes
                // Gets map of failed results from Id to AppSearchResult
                val failedResults = result?.failures
    
                Log.d(TAG, "成功:" + successfulResults.toString())
                Log.d(TAG, "失败:" + failedResults.toString())
            }
    
            override fun onFailure(t: Throwable) {
                Log.d(TAG, t.message.toString())
            }
    
        },
        mainExecutor
    )

    运行,程序打印如下所示:

    com.lonbon.appsearchdemo D/MainActivity: 成功:{new_id_1=null}
    com.lonbon.appsearchdemo D/MainActivity: 失败:{}


    说明存储成功了,接下来我们再插入一条数据,插入代码一致,就不重复展示了,数据如下所示:

    val news2 = News(
        namespace = "new1",
        id = "new_id_1",
        newsTitle = "Huang Linqing is handsome a boy",
        newsContent = "Huang Linqing is an Android development engineer working in Hefei"
    )

    查询数据

    查询数据首先我们要指定查询的范围要就是namespace,相当于指定数据表,毕竟不同表中可能存在相同符合条件的数据。

    val searchSpec = SearchSpec.Builder()
        .addFilterNamespaces("new1")
        .build()

    然后执行查询操作,我们这里查询的关键字是”handsome“

    val searchFuture = Futures.transform(
        sessionFuture,
        Function<AppSearchSession?, SearchResults> {
            it?.search("handsome", searchSpec)
        },
        mainExecutor
    )

    同样的我们使用addCallback方法来检测查询结果,代码如下所示:

    Futures.addCallback(
        searchFuture,
        object : FutureCallback<SearchResults> {
            override fun onSuccess(result: SearchResults?) {
                iterateSearchResults(result)
            }
    
            override fun onFailure(t: Throwable) {
                Log.d(
                    TAG, "查询失败:" + t
                        .message
                )
            }
    
        },
        mainExecutor
    )

    查询成功会返回SearchResults类,我们需要遍历这个实例取出所有数据打印出来,即iterateSearchResults方法,代码如下所示:

    private fun iterateSearchResults(searchResults: SearchResults?) {
        Futures.transform(searchResults?.nextPage, Function<List<SearchResult>, Any> {
            it?.let {
                it.forEach { searchResult ->
                    val genericDocument: GenericDocument = searchResult.genericDocument
                    val schemaType = genericDocument.schemaType
                    if (schemaType == "News") {
                        try {
                            var note = genericDocument.toDocumentClass(News::class.java)
    
                            Log.d(
                                TAG,
                                "查询结果:新闻标题-" + note.newsTitle
                            )
                            Log.d(
                                TAG,
                                "查询结果:新闻内容-" + note.newsContent
                            )
                           
                        } catch (e: AppSearchException) {
                            Log.e(
                                TAG,
                                "Failed to convert GenericDocument to Note",
                                e
                            )
                        }
    
                    }
                }
    
    
            }
    
        }, mainExecutor)
    }

    查询出来的结果是一个集合,所以我们需要遍历集合,并且数据类型需要是News类才可以继续下一步,这里我们将符合条件查询的新闻标题打印出来,结果如下所示:

    D/MainActivity: 查询结果:新闻标题-who is a boy
    .appsearchdemo D/MainActivity: 查询结果:新闻内容-Everyone, guess who is the handsome boy
    .appsearchdemo D/MainActivity: 查询结果:新闻标题-Huang Linqing is a handsome boy
    .appsearchdemo D/MainActivity: 查询结果:新闻内容-Huang Linqing is an Android development engineer working

    这里我们可以看到我们查询的关键字是handsome的时候将两个结果都打印出来了,而第一条结果是新闻标题包含handsome关键字,第二条结果是新闻内容包含关键字,如果我们使用普通的sql,大概需要这么做

    select * from table where newsTitle like %key% or newsContent like %key%

    而使用AppSearch 不需要关心具体匹配的是哪个字段,只要任一字段包含相关内容,就将结果显示出来,有点像百度搜索时,我们可以看到有些关键字是在标题中有些关键字是在内容中而这些内容都可以很快的查询出来。

    我为什么夸自己

    这里我们搜索的关键字是handsome,新闻标题是 Huang Linqing is a handsome boy,黄林晴是个帅气的男孩,这里我并不是故意夸我自己的,而是在学习AppSearch的使用时,我发现了一个bug,那就是上面的代码如果插入的是中文,在搜索时将不会得到任何结果,昨天晚上发现这个问题后我将此问题提给了Google

    Google 也很快给了答复

    不支持中文搜索,这是一个已知问题,并且Google将在新版本中修复,会尽快发布版本,所以我们在新版本发布前知道有这个问题就行了,避免无效检查自己的代码问题。

    删除数据

    删除数据时我们需指定命名空间和数据id,构建一个删除数据的请求,代码如下所示:

    val deleteRequest = RemoveByDocumentIdRequest.Builder("new1")
        .addIds("new_id_2")
        .build()
    val removeFuture = Futures.transformAsync(
        sessionFuture, AsyncFunction {
            it?.remove(deleteRequest)
        },
        mainExecutor
    )

    到这里,我们也看出来了,其实Appsearch的使用,对数据的操作都是先构建一个请求,然后使用Futures去执行,如果需要检测结果的话,就通过Futures.addCallback添加一个回调即可,这里执行删除操作后,我们再次通过关键字”handsome“去查询,会发现就只有一条数据显示出来了,这里执行结果就不在展示了。

    关闭会话

    在开始使用的使用,我们创建了一个
    ListenableFuture<AppSearchSession>,后续所有的数据操作都通过这个会话去建立的,在使用结束后我们需要关闭这个会话,代码如下所示:

    val closeFuture = Futures.transform<AppSearchSession, Unit>(
        sessionFuture,
        Function {
            it?.close()
        }, mainExecutor
    )

    小结

    AppSearch是Jetpack最新推出的组件,AppSearch 是一个搜索库,可以很方便的来实现应用内的搜索功能,AppSearch的 I/O 使用很低,与 SQLite 相比,AppSearch 可能会更高效。但目前个人还是认为针对的问题不同和解决问题的角度不同,和其他数据库没有可比性,选择合适的方案最重要。

    展开全文
  • 1 APP测试基本流程 1.1预估测试周期 测试周期可按项目的开发周期来确定测试时间,一般测试时间为两周(即10个工作日,一人份工作量),根据项目情况以及版本质量可适当缩短或延长测试时间。正式测试前先向主管...

     

    1 APP测试基本流程

    1.1预估测试周期

    测试周期可按项目的开发周期来确定测试时间,一般测试时间为两周(即10个工作日,一人份工作量),根据项目情况以及版本质量可适当缩短或延长测试时间。正式测试前先向主管确认项目整体排期。

    与其他项目强耦合适量增加3-5个工作日,弱耦合增加1-2工作日

    1.2测试资源

    测试任务开始之前,准备测试资源

    1.产品文档
    2.原型图
    3.效果图 即设计交互稿
    4.行为统计分析定义文档
    5.测试设备(测试机,平板,系统iOS、Android,不同分辨率)
    6.测试人员
    7.其他

    1.3分析测试内容

    • 这里就说的通俗一点
    • 比如A要去吃饭,那么他怎么吃饭,用什么吃饭,吃什么饭,吃多少合适。
      • 怎么吃:项目业务流
      • 用什么吃:项目前期准备测试事宜
      • 吃什么饭:明确测试目的,项目背景
      • 吃多少合适:合格点,吃完饭了是不是得确认他是不是吃饱了?

    1.4设计测试计划、测试用例

    古人云:凡事预则立,不预则废。也就是强调预先计划的重要性和必要性

    • 测试计划
      • 测试范围 明确测什么?比如:产品的具体业务需求有哪些?产品是web端的还是移动端的,还是两者都有?
      • 测试策略 明确怎么测。对不同业务需求,具体要有哪些测试类型、测试场景、测试方法。
      • 资源安排 包括测试人员的安排,测试环境是怎样的,测试工具的选择等。
      • 进度安排 在明确测试范围、方法和人员之后,我们要考虑什么时候开始测试,预计要测试多久?以便和开发计划、上线计划衔接。
      • 发布标准 发布标准是测试完成和产品上线需要满足的条件,以便项目内所有角色都有一致认可的目标。怎样才算是测完了?达到怎样的标准才可以上线?
      • 风险预防 最后,我们需要对整个测试过程中可能存在的风险,以及当这些风险发生时的应对措施提前进行一些考虑和准备,并在测试计划中体现出来。
    • 测试用例就不多说了,测试工程师的基本功

    1.5用例评审

    一千个眼里就有一千个哈姆雷特,所以用例评审很重要,这是一个查漏补缺的过程,不光用例层面的补充,也在某种程度上对其他同事也是一种回顾&梳理其他同事的堵塞点

    1.3测试报告

    1. 测试人员对每天测试项目发送测试报告(若无要求,则不需要发送日报)
    2. 日报所含内容:
      • 对当前测试版本质量进行分级
      • 严重阻塞进度的问题提出,提示开发同学优先修改
      • 对版本整体测试进度进行评估
    3. 产品上线前,测试发送测试报告

    2 APP测试点

    2.1 安装

    1. 软件在不同操作系统(Palm OSSymbianLinuxAndroidiOSBlack Berry OS 6.0Windows Phone 7)下安装是否正常
    2. 软件安装后的是否能够正常运行,安装后的文件夹及文件是否写到了指定的目录里
    3. 软件安装各个选项的组合是否符合概要设计说明
    4. 软件安装向导的UI测试
    5. 软件安装过程是否可以取消,点击取消后,写入的文件是否如概要设计说明处理
    6. 软件安装过程中意外情况的处理是否符合需求(如死机,重启,断电)
    7. 安装空间不足时是否有相应提示
    8. 安装后没有生成多余的目录结构和文件
    9. 对于需要通过网络验证之类的安装,在断网情况下尝试一下
    10. 还需要对安装手册进行测试,依照安装手册是否能顺利安装

    2.2 卸载

    1. 直接删除安装文件夹卸载程序是否有提示信息
    2. 测试系统直接卸载程序是否有提示信息。
    3. 测试卸载后文件是否全部删除所有的安装文件夹
    4. 卸载过程中出现的意外情况的测试(如死机、断电、重启)
    5. 卸载是否支持取消功能,单击取消后软件卸载的情况
    6. 系统直接卸载UI测试,是否有卸载状态进度条提示

    2.3 安全性

    2.3.1 通讯安全

    1. 在软件运行中,如有来电,SMSEMSMMS,蓝牙等通讯或充电是,是否能暂定程序,优先处理通讯,并在处理完毕后恢复软件,继续执行
    2. 创立连接时,应用程序因网络连接中断,是否可以告诉用户连接中断的情况
    3. 可以处理通讯延时和中断
    4. HTTPHTTPS覆盖测试
      • APP和后台服务一般是通过http交互,验证http环境下是否正常
      • 外网免费网络中一般都要输入密码,通过SSL认证来访问网络,需要对是使用HTTP Clientlibrary异常做捕获处理
    5. 应用程序关闭,或网络断开不再使用时,应该及时关闭

    2.3.2人机接口安全

    1. 返回桌面应用程序保持可用
    2. 指令顺序有先后
    3. 本机非网络控制和通知控制,其他设置对应用程序不造成影响

    2.3.3 数据安全性

    1. 密码等敏感数据不会保存在设备中,同时密码不会被解码
    2. 输入密码讲不以明文展示
    3. 支付相关的密码一律不被储存在欲输入位置上
    4. 若应用程序可进行备份操作,备份数据应进行加密操作,恢复数据应考虑恢复过程中的异常,通讯中断等
    5. 在数据删除之前,应用程序应当通知用户或者应用程序提供一个取消命令的操作
    6. 应用程序应当能够处理当不允许应用软件连接到个人信息管理的情况
    7. 在没有用户明确许可的前提下不损坏侧除个人信息管理应用程序中的任何内容
    8. 不能再安全警告前,利用显示误导信息欺骗用户,应用程序不应该模拟进行安全警告误导用户
    9. 如果数据库中重要的数据正要被重写, 应及时告知用

    2.4 功能测试

    根据软件说明或用户需求验证App的各个功能实现

    • 采用时间、地点、对象、行为和背景五元素或业务分析等方法分析、提炼App的用户使用场景,对比说明或需求,整理出内在、外在及非功能直接相关的需求,构建测试点,并明确测试标准,若用户需求中无明确标准遵循,则需要参考行业或相关国际标准或准则。
    • 根据被测功能点的特性列丼出相应类型的测试用例对其进行覆盖,如;涉及输入的地方需要考虑等价、边界、负面、异常或非法、场景回滚、关联测试等测试类型对其进行覆盖
    • 在测试实现的各个阶段跟踪测试实现与需求输入的覆盖情况,及时修正业务或需求理解错误

    2.4.1 程序运行

    1. 安装后可正常打开
    2. 注册
      • 用户密码长度
      • 注册后提示
      • 注册成功数据是否前后一致
    3. 登录
      • 登录是否互斥
      • 是否可进行异地登录
      • 是否允许非法登录
      • 使用已在线账号登录,登录系统是否处理正常
      • 使用禁用账号登录系统,系统处理是否正常处理
      • 登录账号密码数据错误登录是否成功
      • 登录超时如何处理
    4. 注销
      • 注销后用户再次登录是否成功
      • 注销后,数据是否已经删除(物理删除,或逻辑删除)

    2.4.2 程序切换

    1. APP切换到后台,再回到app,检查是否停留在上一次操作界面
    2. APP切换到后台,再回到app,检查功能及应用状态是否正常,IOS4IOS5的版本的处理机制有的不一样
    3. app切换到后台,再回到前台时,注意程序是否崩溃,功能状态是否正常,尤其是对于从后台切换回前台数据有自动更新的时候
    4. 手机锁屏解屏后进入app注意是否会崩溃,功能状态是否正常,尤其是对于从后台切换回前台数据有自动更新的时候
    5. App使用过程中有电话进来中断后再切换到app,功能状态是否正常
    6. 当杀掉app进程后,再开启appapp能否正常启动
    7. 出现必须处理的提示框后,切换到后台,再切换回来,检查提示框是否还存在,有时候会出现应用自动跳过提示框的缺陷
    8. 对于有数据交换的页面,每个页面都必需要进行前后台切换、锁屏的测试,这种页面最容易出现崩溃

    2.4.3 保留TOKEN(免登)

    2.4.4 APP更新

    1. 当客户端有新版本时,有更新提示
    2. 当版本为非强制升级版时,用户可以取消更新,老版本能正常使用。用户在下次启动app时,仍能出现更新提示
    3. 当版本为强制升级版时,当给出强制更新后用户没有做更新时,退出客户端。下次启动app时,仍出现强制升级提示
    4. 当客户端有新版本时,在本地不删除客户端的情况下,直接更新检查是否能正常更新

    2.4.5 离线加载

    很多应用都可以加载数据到本地,给用户提供在离线情况下可以浏览

    2.4.6 消息推送

    1. 在不禁用通知的情况下,push消息是可以直接推送到手机且可以在通知栏查看
    2. push消息推送到手机的情况下,可以点击消息进入唤醒且进入APP
    3. push消息是针对用户进行推送的时候,需核实push消息与用户身份是否相符
    4. push消息是否是按照业务规则进行推送
    5. 用户设置免打扰时间内,用户是接收不到push消息的
    6. 测试push时,需真机测试

    2.5 UI测试

    用户界面 (GUI) 测试用于核实用户与App之间的交互,包括用户友好性,人性化测试。  一个好的App要有一个极佳的分辨率,而在其他分辨率下也都能可以运行。GUI 测试的目标是确保用户界面会通过测试对象的功能来为用户提供相应的访问或浏览功能。另外,GUI 测试还可确保 GUI 中的对象按照预期的方式运行,并符合公司或行业的标准

    1. GUI测试主要测试在不同分辨率下,测试用户界面(如菜单、对话框、窗口和其它可视控件)布局、风格是否满足客户要求,文字是否正确,页面是否美观,文字,图片组合是否完美,操作是否友好等。
    2. GUI测试的目标是确保用户界面会通过测试对象的功能来为用户提供相应的访问或浏览功能。确保用户界面符合公司或行业的标准,包括用户友好性、人性化、易操作性测试

    2.6 性能测试

    性能测试用来测试App在真实环境中的运行性能,以及与硬件、网络资源的匹配度,最终度量系统相对于预定义目标的差距,通过极限测试方法,发现系统在极限或恶劣的环境中自我保护能力,主要验证系统的可靠性。 性能测试测试主要通过以下几项测试完成

    2.6.1 负载测试

    负载测试是在一定的软硬件及网络环境下,通过模拟不同的用户,执行一种或多种业务,观察系统在不同负载下的性能表现。在这种测试中,将使测试对象承担不同的工作量,以评测和评估测试对象在不同工作量条件下的性能行为,以及持续正常运行的能力。
    负载测试的目标是确定并确保系统在超出最大预期工作量的情况下仍能正常运行。 此外,负载测试还要评估性能特征,例如,响应时间、事务处理速率和其他与时间相关的方面。

    2.6.2 强度测试

    强度测试是一种性能测试,实施和执行此类测试的目的是找出因资源不足或资源争用而导致的错误。如果内存或磁盘空间不足,测试对象就可能会表现出一些在正常条件下并不明显的缺陷。而其他缺陷则可能由于争用共享资源(如数据库锁或网络带宽)而造成的。强度测试还可用于确定测试对象能够处理的最大工作量。

    2.6.3 稳定性测试

    稳定性测试评价系统在一定负荷情况下,长时间的运行情况。在一定的软硬件及网络环境中,通过模拟大量的用户执行多种业务处理大量数据,使系统在极限环境下长时间运行,目的在于寻找系统的失效点。

    2.7 兼容测试

    兼容适配性测试(配置测试),是核实测试对象在不同的App、硬件配置中的运行情况,测试系统在各种软硬件配置,不同的参数配置下系统具有的功能和性能。  

    在大多数环境中,不同终端、屏幕、OS版本、网络连接的规格都会有所不同,而这些因素都可能运行许多不同的配置环境组合,从而占用不同的资源(如CPU、内存、浏览器版本、OS版本等)。  

    1. 新老版本兼容
    2. 设备兼容
    3. 设备系统兼容
    4. 分辨率兼容
    5. 浏览器兼容

    2.8 接口测试

    服务端一般会提供JSON格式的数据给客户端,所以我们在服务端需要进行接口测试,确保服务端提供的接口并转换的JSON内容正确,对分支、异常流有相应的返回值。此块测试可以采用itest框架进行测试。最方便的是采用httpclient进行接口测试。
    一般来讲,APP做接口测试不是特别适合

    2.9 用户体验可用性测试

    用户体验可用性测试主要是检测用户在理解和使用系统方面到底有多好,是否存在障碍或难以理解的部分。  

    用户体验可用性的测试方法,一般是通过用户访谈,或邀请内测、小范围公测等方式进行,通过不同实验组的运营结果来判断是否存在可用性缺陷。但由于缺乏有效的测试工具,必须要大量的测试样本才能获得比较真实的测试数据,投入资源较多,测试周期较长。

    2.10 网络测试

    手机的网络目前主要分为2G3G4Gwifi

    • 无网络时,执行需要网络的操作,给予友好提示,确保程序不出现crash 
    • 内网测试时,要注意选择到外网操作时的异常情况处理。 
    • 在网络信号不好时,检查功能状态是否正常,确保不因提交数据失败而造成crash 
    • 在网络信号不好时,检查数据是否会一直处于提交中的状态,有无超时限制。如遇数据交换失败时要给予提示。 
    • 在网络信号不好时,执行操作后,在回调没有完成的情况下,退出本页面或者执行其他操作的情况,有无异常情况。此问题也会经常出现程序crash

    2.9 回归测试

    回归测试是以上所有测试完成后的一个最为重要的环节,是App发布、维护阶段,对缺陷进行修复后的测试
    目的是验证缺陷已经得到修复,检测是否引入新的缺陷

    2.9.1 回归测试流程

    1. 在测试策略制定阶段,制定回归测试策略
    2. 确定需要回归测试的版本; 
    3. 测试版本发布后,按照回归测试策略来执行回归测试; 
    4. 回归测试通过,关闭缺陷跟踪单; 
    5. 回归测试不通过,缺陷跟踪单返回给开发人员,开发人员重新修改BUG。再次提交给测试人员回归测试 

    2.9.2 回归测试策略

    1. 完全重复测试:重新执行前期设计的用例,来确认问题修改的真确性和修改的扩散局部影响性;
    2. 选择性重复测试: 
    3. 覆盖修改法:针对被修改的部分,选取或重新构造测试用例验证没有错误再次发 生的选择方法
    4. 周边影响法:该方法包括覆盖修改法,还要分析修改后对扩散的影响; 
    5. 指标达成法:先确定一个达成的指标,基于这种要求选择一个最小的测试用例集合

     

    展开全文
  • 一、App Bundle 简介、 二、App Bundle 定制化分发、 1、应用内更新、 ①、即时更新、 ②、灵活更新、
  • iOS之深入解析App的架构设计

    千次阅读 2021-07-20 15:46:34
    App 架构是软件设计的一个分支,它关心的是如何设计一个 App 的结构。具体来说,它关注于两个方面:如何将 App 分解为不同的接口和概念层次部件,以及这些部件之间和自身的不同操作中 所使用的控制流和数据流路径。 ...
  • RPR, *RPREF 渲染系统配置 RR, *RENDER 渲染 DC, *ADCENTER 设计中心 ctrl+2 ADC, *ADCENTER 设计中心 DCENTER, *ADCENTER 设计中心 MA, *MATCHPROP 特性匹配 TP, *TOOLPALETTES 工具选项板 ctrl+3 CH, *PROPERTIES ...
  • 在2020年初,京东金融App的用户规模已远超几年前,日活也是成倍的增长,同时我们也注意到App崩溃率随着版本迭代一直在小幅度升高。当我们意识到App的崩溃已经伤害到用户日常的使用体验时,崩溃率已达到千分之几。...
  • deviceList = App.devices; //check which devices have not been added by checking the position data for (Iterator iterator = deviceList.iterator(); iterator.hasNext(); ) { Device device = iterator.next...
  • }, /* * 根据object生成key value字符串 * @params obj: any 要map的对象 * @params isSort: boolean 是否根据ASCII字典排序 */ mapObjToKeyValue(obj, isSort = false) { let keys =...
  • middleware, 中间件是一个特殊的url地址处理函数,它被当作 app.use(中间件函数)的参数或者是某个路由处理函数中使用。 中间件是 express 的最大特色,也是最重要的一个设计。Express是一个自身功能极简,完全是...
  • 学习UI设计的时候,经常要接触到页面的布局,布局的方式会直接影响一个APP的视觉效果,好的布局方式,往往能带来舒服的视觉效果,更能得到用户的接受与好评。由于手机屏幕尺寸的限制,无法直接把所有内容在一屏内...
  • 鸿蒙APP开发基础知识

    千次阅读 2021-03-16 16:17:42
    config.json应用配置文件 "app"、"deviceConfig" "module" 配置系统的权限 限定词目录 限定词目录的命名 限定词目录与设备状态的匹配规则 日志工具 日志工具的使用 日志工具类 调试 DevEco Studio编辑器de使用 DS与...
  • 本发明涉及智能终端APP管理方法,特别是涉及一种在双屏智能终端上实现双APP同时运行的方法。背景技术:对于双屏双触控的智能终端,常常需要在两块显示屏上分别显示不同的内容。现有技术中,双屏双触控的智能终端通常...
  • 如果一个个app去分析,那工作量会非常庞大,所以就产生了这个工具AnalysisApp。通过这个工具我已经分析了top 200个app,并可以识别出99个sdk。能够识别的sdk列表要是时间充裕,我会不断完善这个项目。工具使用首先,...
  • 如果一个个app去分析,那工作量会非常庞大,所以就产生了这个工具AnalysisApp。通过这个工具我已经分析了top 200个app,并可以识别出99个sdk。能够识别的sdk列表要是时间充裕,我会不断完善这个项目。工具使用首先,...
  • Model指的是数据,在前端对应的是JavaScript对象。View指的是视图,在前端对应的是DOMViewModel观察Model和View的变化来做更新,实现了数据的双向绑定。前端MVVM框架主要包括:angularJS、reactJS、VueJS二、Vuejs的...
  • Uni-app他来了,实现下拉模糊查询 1.先上效果看看与您想要的效果是否一样 2.一样的话,那下面我来教你,用ctrl+cv 附上Dcloud插件市场的地址 https://ext.dcloud.net.cn/plugin?id=1261 3.导入到编辑器HbuilderX ...
  • 移动app测试总结

    2021-02-24 16:53:33
    移动app测试总结 一、移动app测试流程 第一阶段:需求分析 1.新需求是否合理 2.新旧需求时否存在冲突 3.理出测试重点 4.估算测试时间 5.不熟悉的需求点,确认(负责人,产品) 6.对产品有个内在认识(初衷,流程,...
  • App流失率高,为什么用户总是刚下载就卸载? 怎样让新用户尽快体验产品核心业务? 将App拉新效率提高200%,是怎么做到的? ····· 这几个问题相信也是困扰大多数运营者的难题,用户在App内的使用体验不仅影响App...
  • 本文章使用的是vue+h5+plus技术,结合hbuildx打包的App,实现在App中分享页面到朋友圈以及好友。 下面贴码介绍: <nut-popup v-model="isVisible" position="bottom"> 分享到 <div class="custom-wrap...
  • iOS应用之间跳转 本篇博文将涉及到以下知识点: app应用跳转的原理解析 如何实现两个app应用之间的跳转 如何实现两个app之间跳转到指定界面 二.应用跳转原理 相信从一个应用跳转到另一个应用大家并不陌生,最常见的莫...
  • App 邀请机制是每个产品几乎必做的功能点,它一般以两种形式存在:一是作为常置功能用于推荐,二是作为裂变活动用于邀请。 无论以哪种形式出现,都可以归为社交分享的一种表现方式。相较于营销推广,邀请好友机制...
  • APP中,字体的大小单位一般会用sp,然而在改变系统字体大小时,App字体就会随着系统字体大小改变而改变,这就可能造成APP布局的错位。造成这种情况的原因是,sp单位除了受屏幕密度影响外,还受到用户的字体大小...
  • 混合app测试

    2021-06-09 07:53:39
    1、appium可以测试的对象 原生 :所有控件都是一种开发技术,如android都是java代码组成的控件,ios都是object-c构成的,如日历程序,计算机都是这种原生app。 混合 :原生app无法满足内容快速变更的需要,因此需要...
  • 基于VUE+JQ使用wx-open-launch-app教程 1.一定要用 < script type=“text/wxtag-template” >< script >包裹起来,否者按钮会消失 <wx-open-launch-app id="launch-btn" @error="handleErrorFn" @...
  • app.use1.什么是中间件2.express中的中间件3.总结 1.什么是中间件 中间件就是一个请求处理方法,用其把用户从请求到响应的整个过程分发到多个中间件去处理,这样做的目的是提高代码的灵活性,动态可扩展的。简单的...
  • locationId=${this.formParams.locationId}` this.navigate(url) }, // 设置 位置,通过故障位置选择页面选择完成后返回的值,并渲染到formParams对象中 setSelectLocationData(data){ let locationObj = JSON....
  • Hello World 程序员的经典学习方法,从Hello World开始。不要忘了,先安装python, pip,然后运行pip install Flask,...app = Flask(__name__) @app.route('/') def index(): return '<h1>Hello World<...
  • 机器学习与组合优化问题实例,研究对象是 Graph Matching 。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 138,191
精华内容 55,276
关键字:

匹配对象的app