在代码层面描述软件的可测试性

  质量属性的第五大战术是可测试性战术。什么是可测试性战术,顾名思义,测试就是为了发现错误,那么可测试性战术的目标是允许在完成软件开发的一个增量后,轻松地对软件进行测试。可测试性战术的分类可以由下图所示:

在代码层面描述软件的可测试性


 

  1.记录/回放(Record/playback ):记录/回放是指将捕获跨接口的信息,并将其作为测试专用软件的输入。

  使用命令模式把一个请求或者操作封装到一个对象中,把发出命令的责任和执行命令的责任分割开,委派给不同的对象,可降低行为请求者与行为实现者之间耦合度。在这里,我们通过维护undo和redo两个盛放Command的栈(用List实现),首次执行一个Command时,执行execute()并将其放入undo栈内,同时要清空redo栈;当执行撤销操作时把undo栈内最上面一个Command拿出来执行undo(),然后将其放入redo栈内;执行重做操作时把redo栈内最上面一个Command拿出来执行execute(),然后将其放入undo栈内。

  当点击按钮执行操作时,可在其ActionListener内执行commandManager.executeCommand(newXXXCommand());把命令加入栈中。

public class CommandManager {
 
    private List undoList = new ArrayList();
    private List redoList = new ArrayList();
    
    // 可撤销的步数,-1时无限步
    private int undoCount = -1;
    
    public CommandManager() {
        
        // 可通过配置文件配置撤销步数
        undoCount = 5;
    }
 
    /**
     * 执行新操作
     */
    public void executeCommand(Command cmd) {
        
        // 执行操作
        cmd.execute();
        
        undoList.add(cmd);
        
        // 保留最近undoCount次操作,删除最早操作
        if (undoCount != -1 && undoList.size() > undoCount) {
            undoList.remove(0);
        }
        
        // 执行新操作后清空redoList,因为这些操作不能恢复了
        redoList.clear();
    }
    
    /**
     * 执行撤销操作
     */
    public void undo() {
        if (undoList.size() <= 0) {
            return;
        }
        
        Command cmd = ((Command)(undoList.get(undoList.size() - 1)));
        cmd.undo();
        
        undoList.remove(cmd);
        redoList.add(cmd);
    }
 
    /**
     * 执行重做
     */
    public void redo() {
        if (redoList.size() <= 0) {
            return;
        }
        
        Command cmd = ((Command)(redoList.get(redoList.size() - 1)));
        cmd.execute();
        
        redoList.remove(cmd);
        undoList.add(cmd);
    }

  


  2.将接口与实现分离(Separate interface from implementation )

  将接口与实现分离指的就是将接口与实现分离允许实现的代替。占位实现允许在缺少被占位组件时,对系统的剩余部分进行测试。

  在上面的例子中,我们使用的是命令模式,当然不可避免的要使用接口来进行定义。因此就会使用分离的格式进行测试。

public interface Command {    
    public void execute(); // 执行命令和重做    
    public void undo();  // 执行撤销操作    
}   

  如果缺少接口类的调用,那就会在代码修改时发生大量的变动,使得测试工作也难以进行下去。


  3.特化访问路线/接口

  特化的接口可以独立于程序正常运行,即设计独立的接口仅供测试使用。

  比如在python web开发的Django框架中,我们通过专门的数据库连接来获取到我们的数据库数据,他并不是在程序运行的过程中直接显示的,而是在刚开始进行框架设计的时候就进行了数据的加载。通过更改配置文件,来达到获取数据的目的。

  在settings中创建数据库连接,然后执行脚本,就可以得到我们的数据。

在代码层面描述软件的可测试性

在代码层面描述软件的可测试性
"""
Django settings for django_demo_00 project.

Generated by 'django-admin startproject' using Django 3.0.3.

For more information on this file, see
https://docs.djangoproject.com/en/3.0/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.0/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '!fo8_1bnoyif_rzsg*y4w&b8g4a5r&2pv9j0c-so-2ncrhet_2'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'demo_00_app',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'django_demo_00.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'django_demo_00.wsgi.application'


# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'db_pymysql',
        'USER':'root',
        'PASSWORD':'20173673',
        'HOST':'localhost',
        'PORT':'3306'
    }
}


# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/

STATIC_URL = '/static/'
View Code

  在settings中,有许多的事件都是通过修改配置文件进行的,Django也是通过将需要的接口进行特化,来实现相应功能的实现。


 

  

 

上一篇:Django框架--创建项目与应用


下一篇:django_设置文件