如何用深度强化学习做单元测试代码生成

设计一个用强化学习来生成单元测试代码的系统需要考虑以下几个方面:

Agent:强化学习算法中的智能体,它需要接收当前环境状态,根据策略选择相应的动作并执行。

State:描述当前环境状态的特征。在这个问题中,状态可以包括待测试函数的输入和输出,以及已经生成的测试用例和它们对应的覆盖率等信息。

Action:智能体可以采取的行为,比如在待测试函数输入上添加新的测试用例或修改已有的测试用例。

Environment:整个系统的环境,包括待测试函数、测试框架、测试用例库等。系统需要将当前状态传递给智能体,让它进行决策,并根据执行结果更新状态。

Reward:强化学习算法中的奖励信号,用来指导智能体的决策。在这个问题中,奖励可以是代码覆盖率的提升量,也可以是测试用例数量的增加量。

具体地,可以将状态表示成一个向量,其中包括待测试函数的输入和输出,以及已生成的测试用例和它们对应的覆盖率等信息。智能体每次决策时会基于当前状态 选择一个动作 ​,比如在输入上添加新的测试用例或者修改已有的测试用例。

执行完动作后,系统会返回一个新的状态 和相应的奖励 。奖励可以根据覆盖率的提升量进行设计,比如引入一个目标覆盖率,奖励为当前覆盖率与目标覆盖率之间的差异。同时,还可以设置一些惩罚项,比如每次修改测试用例都会降低一定的分数。

最后,可以使用基于模型的强化学习算法(如DQN)来训练智能体,优化其策略,不断改进生成单元测试代码的能力。

下面是一个简单的案例代码,用强化学习的方法来生成加法函数的单元测试代码。

首先,我们定义待测试的加法函数和测试框架。假设加法函数需要接受两个整数作为输入,并返回它们的和。测试框架可以是任何测试框架,这里我们选择Python自带的unittest框架。

def add(x, y):

return x + y

import unittest

class TestAdd(unittest.TestCase):

def test_add(self):

self.assertEqual(add(1, 2), 3)

接下来,我们可以定义智能体的状态、动作和奖励。

状态 可以包含以下信息:

待测试函数的输入:由两个整数 组成。

已有的测试用例及其覆盖率:包括当前唯一的测试用例 (1,2) 和它的覆盖率(假设已经执行过该测试用例并计算出了它的覆盖率)。

动作 ​可以有以下两种:

增加新的测试用例:在输入空间中随机选择一个点 ,添加新的测试用例 并计算它的覆盖率。

修改现有的测试用例:对于已有的测试用例 ,在输入空间中随机选择一个点 ,将之前的测试用例 替换成新的测试用例 并计算它的覆盖率。

奖励 可以基于测试用例的覆盖率构建,具体地,可以设置目标覆盖率​,然后奖励可以设计成:

其中是更新状态后得到的新的覆盖率, 是上一次的覆盖率。如果新的覆盖率比旧的要高,则给予奖励 10 分;反之则惩罚 -10 分。

最后,我们可以使用 DQN 算法来训练智能体,优化其策略,不断改进生成单元测试代码的能力。具体来说,我们可以使用 Keras 的深度神经网络模型来近似 Q 函数,使用均方误差损失函数进行训练。同时,也需要设置合适的超参数,例如贪心策略的初始值、学习率等等。

完整的代码如下所示:

import random
import numpy as np
from keras.models import Sequential
from keras.layers.core import Dense
from keras.optimizers import Adam
 
 
# 加法函数
def add(x, y):
    return x + y
 
 
# 测试框架
import unittest
 
 
class TestAdd(unittest.TestCase):
    def test_add(self):
        self.assertEqual(add(1, 2), 3)
 
 
# 定义智能体的状态、动作和奖励
class RLAgent:
    def __init__(self):
        self.state_dim = 3  # 输入空间维度(x, y, coverage)
        self.action_dim = 2  # 动作空间维度(add or modify)
        self.memory = []  # 记忆库(用于存储状态序列、动作序列、奖励序列、下一状态序列)
        self.gamma = 0.95  # 折扣因子
        self.epsilon = 1.0  # 初始 epsilon 值
        self.epsilon_min = 0.01  # 最小 epsilon 值
        self.epsilon_decay = 0.999  # epsilon 衰减因子
        self.learning_rate = 0.001  # 学习率
        # 创建神经网络模型
        self.model = Sequential()
        self.model.add(Dense(24, input_dim=self.state_dim, activation='relu'))
        self.model.add(Dense(24, activation='relu'))
        self.model.add(Dense(self.action_dim, activation='linear'))
        self.model.compile(loss='mse', optimizer=Adam(lr=self.learning_rate))
 
    # 根据当前状态选取动作(epsilon-greedy 策略)
    def act(self, state):
        if np.random.rand() <= self.epsilon:
            return random.randrange(self.action_dim)
        else:
            q_values = self.model.predict(state)
            return np.argmax(q_values[0])
 
    # 记忆当前状态、动作、奖励和下一状态
    def remember(self, state, action, reward, next_state):
        self.memory.append((state, action, reward, next_state))
 
    # 更新 Q 函数
    def replay(self, batch_size):
        if len(self.memory) < batch_size:
            return
        minibatch = random.sample(self.memory, batch_size)
        for state, action, reward, next_state in minibatch:
            target = reward + self.gamma * np.amax(self.model.predict(next_state)[0])
            target_f = self.model.predict(state)
            target_f[0][action] = target
            self.model.fit(state, target_f, epochs=1, verbose=0)
        if self.epsilon > self.epsilon_min:
            self.epsilon *= self.epsilon_decay
 
if __name__ == "__main__":
    env = TestAdd() # 环境
    agent = RLAgent() # 智能体
    state = np.array([[1, 2, 0.0]]) # 初始状态
    batch_size = 32 # 批大小
    for e in range(100):  # 训练轮数
        action = agent.act(state)  # 获取动作
        if action == 0:  # 增加新的测试用例
            x_prime, y_prime = random.randint(0, 100), random.randint(0, 100)
            new_test_case = (x_prime, y_prime)
            coverage = 1.0 - abs(add(x_prime, y_prime) - add(1, 2)) / add(1, 2)
            reward = 10.0 if coverage > state[0][-1] else -10.0
            next_state = np.array([[x_prime, y_prime, coverage]])
            agent.remember(state, action, reward, next_state)
            state = next_state
        elif action == 1:  # 修改现有的测试用例
            x_prime, y_prime = random.randint(0, 100), random.randint(0, 100)
            modified_test_case = (x_prime, y_prime)
            coverage = 1.0 - abs(add(x_prime, y_prime) - add(1, 2)) / add(1, 2)
            reward = 10.0 if coverage > state[0][-1] else -10.0
            next_state = np.array([[x_prime, y_prime, coverage]])
            agent.remember(state, action, reward, next_state)
            state = next_state
 
        agent.replay(batch_size)  # 更新 Q 函数

在训练过程中,我们将初始状态设置为 (1,2,0),即输入为 (1,2),覆盖率为 0。

每次执行增加或修改操作后,会根据新的测试用例计算出相应的覆盖率,并基于覆盖率的提升量给予奖励或惩罚。

在训练结束后,我们可以使用新生成的测试用例来验证加法函数的正确性。 需要注意的是,这只是一个简单的案例代码,实际情况下需要仔细设计Agent的状态、动作和奖励,并针对具体问题进行调参和优化。同时,需要注意训练数据的质量和数量,以及如何划分训练集和测试集,以确保模型具有良好的泛化能力。

实际工程中使用时,针对参数的生成逻辑可能需要AST静态分析的能力支撑才会有比较好的效果,另外在模型训练过程中,单测代码的实时执行+覆盖率反馈也需要工程能力支撑。

另外因为在实际项目的单测代码中,因为很多依赖服务、db、中间件等需要mock,结合精准化测试工程可以准确定位到需要mock的代码行,mock的数据也可以作为state的特征之一。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
【资源介绍】 基于DQN深度强化学习解决三维在线装箱问题python源码+项目说明.zip 问题描述 物流公司在流通过程中,需要将打包完毕的箱子装入到一个货车的车厢中,为了提高物流效率,需要将车厢尽量填满,显然,车厢如果能被100%填满是最优的,但通常认为,车厢能够填满85%,可认为装箱是比较优化的。 设车厢为长方形,其长宽高分别为L,W,H;共有n个箱子,箱子也为长方形,第i个箱子的长宽高为li,wi,hi(n个箱子的体积总和是要远远大于车厢的体积),以下假设和要求: 1. 长方形的车厢共有8个角,并设靠近驾驶室并位于下端的一个角的坐标为(0,0,0),车厢共6个面,其中长的4个面,以及靠近驾驶室的面是封闭的,只有一个面是开着的,用于工人搬运箱子; 2. 需要计算出每个箱子在车厢中的坐标,即每个箱子摆放后,其和车厢坐标为(0,0,0)的角相对应的角在车厢中的坐标,并计算车厢的填充率。 运行环境 主机 |内存 | 显卡 | IDE | Python | torch -----|------|------|-----|--------|----- CPU:12th Gen Intel(R) Core (TM) i7-12700H 2.30 GHz | 6GB RAM | NVIDIA GEFORCE RTX 3050 | Pycharm2022.2.1 | python3.8 | 1.13.0 思路 (1)箱子到来后,根据车厢的实际空间情况,按照策略选择放置点; (2)当摆放箱子时,以6种姿态摆放,并对其进行评估,使用评估值最高的姿态将箱子摆放在选中的角点上; (3)重复以上步骤,直到摆放完毕。 建立模型 在车厢内部设置坐标系,靠近驾驶室并位于下端的一个角的坐标为(0,0,0),相交于原点的车厢长边、宽边和高边分别为x轴,y轴和z轴方向,L、W、H分别为车厢的长、宽、高。箱子具有六种摆放姿态,分别以箱子的长宽、长高、宽高平面为底,旋转90°可以得到另外三种摆放姿态。 核心 # 箱子放置策略 本算法将角点作为车厢内部空间中箱子的摆放位置,每次放入新箱子后搜索新生成的角点,当向车厢中放入第一个箱子时,假设车厢中只有原点一个角点,当一个箱子放入后,会产生新的角点,再放置箱子后,又会产生新的角点。 建立箱子可放置点列表,表示箱子i到来时,车厢内部所有可选的摆放位置,在放置新箱子后更新可放置点列表,并记录已放置箱子到车厢顶部距离,用于后续的奖励函数。 # DQN (1)设置一些超参数,包括ε-greedy使用的ε,折扣因子γ,目标网络更新频率,经验池容量等。 (2)由于给定的箱子数据较少,为了增加模型训练数据数量,将给定的箱子数据打乱,以随机的形式生成并保存,作为训练数据,训练网络模型。 (3)奖励函数 使用x-y平面中两个最大剩余矩形面积(如下图)之和与箱子到车厢顶部的距离作为奖励值R,奖励函数表示如下 【说明】 该项目是个人毕设项目,答辩评审分达到95分,代码都经过调试测试,确保可以运行!欢迎下载使用,可用于小白学习、进阶。 该资源主要针对计算机、通信、人工智能、自动化等相关专业的学生、老师或从业者下载使用,亦可作为期末课程设计、课程大作业、毕业设计等。 项目整体具有较高的学习借鉴价值!基础能力强的可以在此基础上修改调整,以实现不同的功能。 欢迎下载交流,互相学习,共同进步!
【资源说明】 毕业设计 基于Python深度强化学习的云工作流调度系统源码+详细注释+全部数据资料+部署文档(优秀项目) 关键词:有向无环图,工作流,深度强化学习,图神经网络; 蒙特卡洛树搜索 Python 3.9.7 - torch 1.10 - gym 0.21.0 - networkx 2.6.3 1. 将 Env/___.py 文件注册在gym的环境中; 2. 运行 DAGs_generator.py 生成 train dataset, test dataset. 3. 修改环境代码适应生成数据集的路径; 4. 运行 PPO/DRLagent.py 训练网络; 5. 运行 PPO/DRLtest.py 测试推理。 5. 运行baseline_tableau.py 得出baseline算法效果 5. 运行MonteCarloTreeSearch.py 得出MCTS算法效果 马尔可夫决策过程建模 ### 状态空间 1. 当前执行的时间(1维) 2. 当前资源中剩余的 CPU 资源(1维) 3. 当前资源中剩余的 Memory 资源(1维) 4. Ready_task 任务列表(长度为 10)中的任务要求时间(30维)如果不足30空位补-1 5. Ready_task 任务列表中的 CPU 要求资源(30维) 如果不足30空位补-1 6. Ready_task 任务列表中的 Memory 要求资源(30维) 如果不足30空位补-1 7. 当前未完成 DAG 部分的最大路径长度(1维) 8. 当前未完成 DAG 部分的子节点数(1维) 9. 超出 Ready_task 任务列表长度且准备好的任务的时间要求总和(1维) 10. 超出 Ready_task 任务列表长度且准备好的任务的 CPU 要求总和(1维) 11. 超出 Ready_task 任务列表长度且准备好的任务的 Memory 要求总和(1维) 共98维状态。 更多项目细节及介绍,请见资源中的项目说明文档。 参数设定为: size = [20,30,40,50,60,70,80,90] #DAG中任务的数量 max_out = [1,2,3,4,5] #DAG节点的最大出度 alpha = [0.5,1.0,1.5] #控制DAG 的形状 beta = [0.0,0.5,1.0,2.0] #控制 DAG 的规则度 具体的实现细节如下: 1. 根据公式$length=\frac{\sqrt{size}}{alpha}$计算出生成DAG的层数,并计算平均每层的数量$\frac{size}{length}$. 2. 在以均值为$\frac{size}{length}$,标准差为$beta$的正态分布中采样每层的任务数并向上取整,这样随机采样得到的总任务数可能有偏差,随机在某几层添加或者删除任务,使DAG总任务数等于$size$。 3. 对于第一层到倒数第二层:每一个任务随机在[0, $max\_out]$,并随机连接$n$个下一层的任务。 4. 最后给所有没有入边的任务添加Start作为父节点,所有没有出边的任务添加Exit任务作为子节点,至此一个随机的DAG就生成好了。 在这里$alpha$控制的是DAG的整体形状,如果$alpha$越小,DAG越长,$alpha$越大,DAG越短。 【备注】 1、该项目是个人高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(如软件工程、计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
深度强化学习路径规划c代码是一个基于深度学习框架和强化学习算法的路径规划代码。它可以通过学习环境和奖励函数,训练出一个智能体,使其能够生成适合特定环境的路径,从而解决路径规划问题。 该代码采用了深度学习中的神经网络模型来实现智能体的训练,并结合了强化学习中的价值函数和策略函数来确定最优路径。具体而言,代码包含以下主要步骤: 1. 定义环境:该代码需要用户定义路径规划问题的环境,包括地图、起点、终点等信息。 2. 定义奖励函数:为了使智能体能够最优地完成路径规划任务,需要定义合适的奖励函数。例如,当智能体走过正确的路径时给予正向奖励,走错则给予负向奖励。 3. 定义神经网络模型:该代码使用了深度学习中的卷积神经网络模型,用于实现智能体的训练。 4. 定义价值函数和策略函数:通过强化学习中的价值函数和策略函数来确定最优路径。价值函数用于评估智能体在特定状态下的优劣,策略函数用于指导智能体在下一个状态应该采取哪些行动。 5. 训练智能体:通过在环境中随机采样数据,计算奖励函数和更新神经网络模型,训练智能体的表现力。 6. 测试智能体:在训练完成后,通过让智能体在新的环境中进行路径规划,评估其表现,从而判断智能体是否达到预期效果。 综上所述,深度强化学习路径规划c代码是一种高效、智能并且可以灵活适应各种路径规划场景的编程工具,其应用范围广泛,可以为机器人、自动化设备等智能系统提供强大的路径规划能力,有着巨大的潜力和应用价值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值