第二次结对作业

这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/SE2024
这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/SE2024/homework/13281
这个作业的目标 基于第一次结对作业的原型设计进行改进,用代码实现一个项目信息交流平台
学号 102201635
结对成员 10221636 黄森福 102201635 高鑫源
结对同学博客链接 https://www.cnblogs.com/hsf-/p/18456325
github仓库项目地址 https://github.com/zaohuan/102201635-102201636

1.具体分工

黄森福 高鑫源
首页UI的设计,分类导航栏的设计,登录注册,修改个人信息、密码前后端的实现 bug的修复 我的页面ui的设计,创建项目,项目详情,修改项目前后端的实现 bug的修复 单元测试的书写

2.PSP表格

PSP 预估耗时(分钟) 实际耗时(分钟)
计划 60 80
估计这个任务需要多少时间 20 30
开发 2000 2400
需求分析 (包括学习新技术) 480 600
生成设计文档 30 20
设计复审 30 20
代码规范 (为目前的开发制定合适的规范) 30 90
具体设计 60 90
具体编码 2000 2400
代码复审 60 60
测试(自我测试,修改代码,提交修改) 150 180
报告 60 60
测试报告 30 40
计算工作量 10 10
事后总结, 并提出过程改进计划 30 30
合计 3050 3710

3.解题思路描述与设计实现说明

3.1流程图


根据客户现实困扰 我们的软件应该是一个信息发布平台 它能让想要参加项目的用户找到心仪的项目 让缺少队友的项目能够通过创建发布项目来达到招募队友的目的,而对于聊天的需求,目前qq和微信是中国目前最成熟且最流行的交流平台 所以我们的软件在这一方面没有优势,进行实时交流的功能并不是我们软件的核心功能。

3.2创建项目

<template>
  <view class="container">
    <view class="form-item">
      <text>项目名称:</text>
      <input v-model="projectName" placeholder="请输入项目名称" />
    </view>
    
    <view class="form-item">
      <text>项目简介:</text>
      <uni-easyinput 
        type="textarea" 
        autoHeight 
        v-model="projectDescription" 
        placeholder="请输入项目简介" 
      ></uni-easyinput>
    </view>
    
    <view class="form-item">
      <text>项目分类:</text>
      <picker value="selectedCategory" :range="categories" @change="onCategoryChange">
        <view class="picker">
          {{ categories[selectedCategory] || '请选择项目分类' }}
        </view>
      </picker>
    </view>
    
    <view class="form-item">
      <text>项目人数规模:</text>
      <input 
        type="number" 
        v-model="projectScale" 
        placeholder="请输入目前参与项目的人数(请输入数字)" 
        @input="validateScale" 
      />
    </view>


    <view class="form-item">
      <text>是否缺人:</text>
      <picker value="selectedQue" :range="ques" @change="onQueChange">
        <view class="picker">
          {{ ques[selectedQue] || '请选择' }}
        </view>
      </picker>
    </view>

    <view class="form-item">
      <text>项目状态:</text>
      <picker value="selectedState" :range="states" @change="onStateChange">
        <view class="picker">
          {{ states[selectedState] || '请选择项目状态' }}
        </view>
      </picker>
    </view>
	<view class="form-item">
	  <text>联系方式:</text>
	  <input v-model="lianxi" placeholder="请输入联系方式" />
	</view>
    <button @click="createProject">创建项目</button>
  </view>
</template>

<script>
export default {
  data() {
    return {
      projectName: '',
      projectDescription: '',
      projectScale: '',
      selectedCategory: null,
      selectedState: null,
      selectedQue: null,
      categories: ['自然科学', '工程技术', '医学健康', '社会科学', '人文历史', '交叉学科'],
      states: ['准备中', '进行中', '已完结'],
      ques: ['是', '否'],
	  lianxi:null,
    };
  },
  methods: {
	  validateScale() {
	      const isValid = /^[0-9]*$/.test(this.projectScale);
	      if (!isValid) {
	        uni.showToast({
	          title: '请输入有效的数字',
	          icon: 'none'
	        });
	        this.projectScale = this.projectScale.replace(/[^0-9]/g, ''); // 只保留数字
	      }
	    },
    onCategoryChange(e) {
      this.selectedCategory = e.detail.value;
    },
    onStateChange(e) {
      this.selectedState = e.detail.value;
    },
    onQueChange(e) {
      this.selectedQue = e.detail.value;
    },
    goBack() {
      uni.navigateBack({
        delta: 1
      });
    },
    async createProject() {
      if (!this.projectName || !this.projectDescription || 
          (this.selectedCategory === null && this.selectedCategory !== 0) || 
          !this.projectScale || 
          (this.selectedState === null && this.selectedState !== 0) || 
          (this.selectedQue === null && this.selectedQue !== 0)||!this.lianxi) {
        uni.showToast({
          title: '请填写所有字段',
          icon: 'none'
        });
        return;
      }

      const nameExists = await this.checkProjectName(this.projectName);
      if (nameExists) {
        uni.showToast({
          title: '项目名称已存在,请使用其他名称',
          icon: 'none'
        });
        return;
      }

      const projectData = {
        name: this.projectName,
        description: this.projectDescription,
        category: this.categories[this.selectedCategory],
        scale: this.projectScale,
        state: this.states[this.selectedState],
        que: this.ques[this.selectedQue],
		lianxi:this.lianxi,
      };

      try {
        const usernameRes = await uni.getStorage({
          key: 'username'
        });
        const username = usernameRes.data; 
        projectData.username = username;
        console.log(projectData);
        
        await uniCloud.callFunction({
          name: 'createProject',
          data: projectData
        });

        uni.showToast({
          title: '项目创建成功',
          icon: 'success'
        });

        uni.setStorage({
          key: 'projectData',
          data: projectData,
          success: () => {
            uni.navigateTo({
              url: '/pages/projectdetail/projectdetail'
            });
          }
        });

        this.resetForm();
      } catch (error) {
        console.error(error);
        uni.showToast({
          title: '项目创建失败',
          icon: 'none'
        });
      }
    },
    async checkProjectName(name) {
      const res = await uniCloud.callFunction({
        name: 'checkProjectName',
        data: { name }
      });
      return res.result;
    },
    resetForm() {
      this.projectName = '';
      this.projectDescription = '';
      this.projectScale = '';
      this.selectedCategory = null;
      this.selectedState = null;
      this.selectedQue = null;
	  this.lianxi=null;
    }
  }
};
</script>

<style>
.container {
  padding: 20px;
}
.form-item {
  margin-bottom: 15px;
}
input {
  padding: 10px;
  justify-content: center;
  margin: 10px 0;
  border: 1px solid #ccc;
}
button {
  width: 100%;
  padding: 10px;
  background-color: #007aff;
  color: #fff;
  border: none;
  border-radius: 5px;
}
.picker {
  justify-content: center;
  padding: 8px;
  border: 1px solid #ccc;
  border-radius: 4px;
  background-color: #f9f9f9;
  text-align: center;
}
</style>

云函数createProject

const cloud = require('crypto');


const db = uniCloud.database();

exports.main = async (event, context) => {
  // 解构参数
  const { name, description, category, scale, state,que,username,lianxi } = event;

  // 检查必填参数是否存在
  if (!name || !description || !category || !scale|| !state||!que||!username||!lianxi) {
    return {
      success: false,
      error: '缺少必要的参数'
    };
  }

  try {
    // 写入数据到数据库
    await db.collection('projects').add({
      data: {
        name,
        description,
        category,
        scale,
		state,
		que,
		username,
		lianxi,
        createdAt: new Date()
      }
    });
    
    return {
	  
      success: true
    };
  } catch (error) {
    console.error('Error adding project:', error);
    return {
      success: false,
      error: error.message || '数据库写入失败'
    };
  }
};

云函数:checkProjectName

exports.main = async (event) => {
  const { name } = event; // 从请求中获取项目名称
  const db = uniCloud.database();
  
  // 查询数据库,检查名称是否存在
  const result = await db.collection('projects').where({
    'data.name': name
  }).get();

  return result.data.length > 0; // 如果找到项目,返回 true
};

当用户点击“创建项目”按钮时,数据从前端流向后端云函数。此时,前端会收集所有输入的字段,并将其打包成一个对象,提交到云函数中进行处理(其中username直接使用注册登录时的本地数据),createProject云函数接收从前端传来的项目数据,并将其存储到数据库中。数据通过 event 参数传递给云函数后,将这些数据写入 projects 集合。checkProjectName云函数作用于在项目创建之前,需要验证项目名称是否已经存在,避免重名项目的创建。

3.3修改项目

<template>
  <view class="container">
    <view class="form-item">
      <text>项目名称:</text>
      <input v-model="projectName" placeholder="请输入项目名称" />
    </view>
    
    <view class="form-item">
      <text>项目简介:</text>
      <uni-easyinput 
        type="textarea" 
        autoHeight 
        v-model="projectDescription" 
        placeholder="请输入项目简介" 
      ></uni-easyinput>
    </view>
    
    <view class="form-item">
      <text>项目分类:</text>
      <picker value="selectedCategory" :range="categories" @change="onCategoryChange">
        <view class="picker">
          {{ categories[selectedCategory] || '请选择项目分类' }}
        </view>
      </picker>
    </view>
    
    <view class="form-item">
      <text>项目人数规模:</text>
      <input 
        type="number" 
        v-model="projectScale" 
        placeholder="请输入目前参与项目的人数(请输入数字)" 
        @input="validateScale" 
      />
    </view>
    
    <view class="form-item">
      <text>是否缺人:</text>
      <picker value="selectedQue" :range="ques" @change="onQueChange">
        <view class="picker">
          {{ ques[selectedQue] || '请选择' }}
        </view>
      </picker>
    </view>
    
    <view class="form-item">
      <text>项目状态:</text>
      <picker value="selectedState" :range="states" @change="onStateChange">
        <view class="picker">
          {{ states[selectedState] || '请选择项目状态' }}
        </view>
      </picker>
    </view>
    <view class="form-item">
      <text>联系方式:</text>
      <input v-model="lianxi" placeholder="请输入联系方式" />
    </view>
    <button @click="updateProject">修改项目</button>
  </view>
</template>

<script>
export default {
  data() {
    return {
      projectName: '',
      projectDescription: '',
      projectScale: '',
      categories: ['自然科学', '工程技术', '医学健康', '社会科学', '人文历史', '交叉学科'],
      states: ['准备中', '进行中', '已完结'],
      ques: ['是', '否'],
      selectedCategory: undefined,
      selectedState: undefined,
      selectedQue: undefined,
      projectId: '' ,// 用于存储项目ID
	  lianxi:'',
    };
  },
  onLoad(options) {
    this.projectId = options.id; // 获取传递过来的项目 ID
    this.getProjectDetails(this.projectId); // 加载项目的详细信息
  },
  methods: {
	  validateScale() {
	      const isValid = /^[0-9]*$/.test(this.projectScale);
	      if (!isValid) {
	        uni.showToast({
	          title: '请输入有效的数字',
	          icon: 'none'
	        });
	        this.projectScale = this.projectScale.replace(/[^0-9]/g, ''); // 只保留数字
	      }
	    },
    async getProjectDetails(id) {
      const res = await uniCloud.callFunction({
        name: 'getProjectDetails',
        data: { id }
      });
      if (res.result) {
        const project = res.result;
        this.projectName = project.data.name;
        this.projectDescription = project.data.description;
        this.selectedCategory = this.categories.indexOf(project.data.category);
        this.projectScale = project.data.scale;
        this.selectedState = this.states.indexOf(project.data.state);
        this.selectedQue = this.ques.indexOf(project.data.que);
		this.lianxi = project.data.lianxi;
      }
    },
    async updateProject() {
      if (!this.projectName || !this.projectDescription || this.selectedCategory === undefined || !this.projectScale || this.selectedState === undefined || this.selectedQue === undefined||!this.lianxi) {
        uni.showToast({
          title: '请填写所有字段',
          icon: 'none'
        });
        return;
      }
      
      const projectData = {
        id: this.projectId,
        name: this.projectName,
        description: this.projectDescription,
        category: this.categories[this.selectedCategory],
        scale: this.projectScale,
        state: this.states[this.selectedState],
        que: this.ques[this.selectedQue],
		lianxi:this.lianxi,
      };

      try {
        await uniCloud.callFunction({
          name: 'updateProject',
          data: projectData
        });
        uni.showToast({
          title: '项目修改成功',
          icon: 'success'
        });
        uni.navigateTo({
          url: '/pages/myProject/myProject' // 修改成功后跳转到 myproject 页面
        });
      } catch (error) {
        console.error(error);
        uni.showToast({
          title: '项目修改失败',
          icon: 'none'
        });
      }
    },
    onCategoryChange(e) {
      this.selectedCategory = e.detail.value;
    },
    onStateChange(e) {
      this.selectedState = e.detail.value;
    },
    onQueChange(e) {
      this.selectedQue = e.detail.value;
    },
  }
};
</script>

<style>
.container {
  padding: 20px;
}
.form-item {
  margin-bottom: 15px;
}
input {
  padding: 10px;
  justify-content: center;
  margin: 10px 0;
  border: 1px solid #ccc;
}
button {
  background-color: #007AFF;
  color: white;
  padding: 10px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
.picker {
  justify-content: center;
  padding: 8px;
  border: 1px solid #ccc;
  border-radius: 4px;
  background-color: #f9f9f9;
  text-align: center;
}
</style>

云函数getProjectDetails

// getProjectDetails.js
const db = uniCloud.database();

exports.main = async (event, context) => {
  const { id } = event;

  try {
    const res = await db.collection('projects').doc(id).get();
    if (res.data.length > 0) {
      return res.data[0]; // 返回项目详细信息
    } else {
      return { error: '未找到该项目' };
    }
  } catch (error) {
    return { error: error.message };
  }
};
const db = uniCloud.database();

exports.main = async (event, context) => {
  const { id, name, description, category, scale, state, que, lianxi } = event;

  // 准备要更新的数据
  const updateData = {};
  
  // 将字段放入 data 对象中
  updateData.data = {};
  
  if (name) updateData.data.name = name;
  if (description) updateData.data.description = description;
  if (category) updateData.data.category = category;
  if (scale) updateData.data.scale = scale;
  if (state) updateData.data.state = state;
  if (que) updateData.data.que = que;
  if (lianxi) updateData.data.lianxi = lianxi;
  try {
    const res = await db.collection('projects').doc(id).update(updateData);

    if (res.updated === 1) {
      return { success: true };
    } else {
      return { error: '未更新任何项目或未找到项目' };
    }
  } catch (error) {
    return { error: error.message };
  }
};

当用户修改项目数据时,表单数据打包成 projectData 对象,并通过 uniCloud.callFunction 提交给云函数 updateProject。代码除了对所有字段必须全部有输入,项目人数输入进行数字验证外,还实现了每次点击编辑页面时,会显示上次内容的效果。页面加载时,getProjectDetails 云函数从数据库中读取项目的详细信息,并将数据返回前端显示在表单中,用户修改项目数据后,updateProject 云函数将更新的数据写入数据库,前端根据云函数返回的结果,进行成功或失败的提示和页面跳转。

4.附加特点设计与展示

将项目种类分为6大类,便于便于寻找心仪的项目

<template>
    <view>
        <view class="image1">
            <view class="icon-container" @click="navigateToPage(1)">
                <image class="icon" :src="src1"></image>
                <text class="icon-text">自然科学</text>
            </view>
            <view class="icon-container" @click="navigateToPage(2)">
                <image class="icon" :src="src2"></image>
                <text class="icon-text">工程技术</text>
            </view>
            <view class="icon-container" @click="navigateToPage(3)">
                <image class="icon" :src="src3"></image>
                <text class="icon-text">医学健康</text>
            </view>
        </view>
        <view class="image2">
            <view class="icon-container" @click="navigateToPage(4)">
                <image class="icon" :src="src4"></image>
                <text class="icon-text">社会科学</text>
            </view>
            <view class="icon-container" @click="navigateToPage(5)">
                <image class="icon" :src="src5"></image>
                <text class="icon-text">人文历史</text>
            </view>
            <view class="icon-container" @click="navigateToPage(6)">
                <image class="icon" :src="src6"></image>
                <text class="icon-text">交叉学科</text>
            </view>
        </view>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                src1: "/static/1.png",
                src2: "/static/2.png",
                src3: "/static/3.png",
                src4: "/static/4.png",
                src5: "/static/5.png",
                src6: "/static/6.png"
				}
			},
		methods: {
	        navigateToPage(pageIndex) {
	            let targetUrl = '';
	            // 根据图片点击跳转到不同页面
	            switch(pageIndex) {
	                case 1:
	                    targetUrl = '/pages/daohang1/daohang1';
	                    break;
	                case 2:
	                    targetUrl = '/pages/daohang2/daohang2';
	                    break;
	                case 3:
	                    targetUrl = '/pages/daohang3/daohang3';
	                    break;
	                case 4:
	                    targetUrl = '/pages/daohang4/daohang4';
	                    break;
	                case 5:
	                    targetUrl = '/pages/daohang5/daohang5';
	                    break;
	                case 6:
	                    targetUrl = '/pages/daohang6/daohang6';
	                    break;
	                default:
	                    console.error('未知的页面索引');
	                    return;
	            }
	            // 跳转到目标页面
	            uni.navigateTo({
	                url: targetUrl
				});
			}
		}
}
</script>

<style>
    .image1, .image2 {
        display: flex;
        flex-direction: row;
        flex-wrap: nowrap; 
        width: 100%; 
        margin: 10px 0; 
        justify-content: space-between;
    }

    .icon-container {
        display: flex;
        flex-direction: column; 
        align-items: center;
        width: 30%; 
    }

    .icon {
        width: 100%; 
        height: 200rpx;
        border-radius: 30px; 
    }

    .icon-text {
        margin-top: 5px;
        text-align: center; 
    }
</style>



5.目录说明和使用说明

5.1目录组织结构


uniCloud:存放与 UniCloud 云服务相关的内容,如云函数、数据库等。这是阿里云的云环境配置目录。
.hbuilderx:用于存储 HBuilderX IDE 的相关配置文件。
dist:用于存放项目的编译打包后的文件,供发布部署时使用。
pages:存放项目的页面文件
static:用于存放静态资源文件
uni_modules:存放 Uni-app 的插件模块
unpackage:这是 HBuilderX 的打包相关文件夹,包含编译后生成的中间
manifest.json:项目的全局配置文件,包括应用名称、版本号、图标等信息,Uni-app 的运行环境和平台打包相关配置也在这里定义。
pages.json:定义应用的页面路由、导航栏样式、页面标题等,是 Uni-app 页面管理的核心配置文件。
App.vue:,index.html:,main.js,readme.md,uni.promisify.adaptor.js,uni.scss:uniapp的HBuilderX编译环境自带模版文件,在编写项目工程中没有修改过
编写过程中主要编写到的文件目录有:uniCloud,pages,static,pages.json

5.2测试人员运行操作

搜索进入uniapp官方网站,注册一个账号,下载HbuilderX,联系QQ:2796608260,发送你的账号注册邮箱并说明是测试人员身份,我会将你添加为云空间的管理成员,鼠标右击目录中的uniCloud,关联云空间即可。

6.界面展示

登录界面

首页界面

创建项目


“我的”

我的项目




身份完善

登录及注册页面

打开app:点开app图标即可
登录:第一次登录需先注册,注册后输入用户名及密码即可登录
注册:输入用户名,输入两次密码即可注册

首页

分类导航功能:可以根据自己感兴趣的方向来查看对应的项目
搜索项目:可以根据关键词检索对应项目
推荐项目:会展示项目状态为“准备中”“进行中”项目的信息
创建项目:点击右上角加号,点击“创建项目”,填写项目详细信息,创建项目信息后跳转到项目详情页面。

创建项目页面

创建项目:填写项目名称、描述等信息,创建并且发布新项目。

我的项目列表

项目信息:点击“我的” 点击“我的项目”,您可以查看创建项目的详细信息,包括项目名称、描述。
修改项目:点击一个项目,进入项目详情界面,可以修改项目信息或删除项目

修改信息

修改/完善个人信息:在我的页面,点击对应按钮,可以更改自己的真实姓名,院系,身份等信息

7.单元测试

describe('ProjectDetail.vue', () => {
  beforeEach(() => {
    // 模拟 uniCloud 和 uni 对象
    global.uniCloud = {
      callFunction: jest.fn(),
    };
    global.uni = {
      getStorage: jest.fn(),
      navigateBack: jest.fn(),
      showToast: jest.fn(),
    };
  });

  it('应该在加载时从存储中加载项目数据', async () => {
    const projectData = {
      name: '测试项目',
      description: '项目描述',
      category: '分类A',
      scale: '10',
      que: '没有',
      state: '进行中',
      username: 'testuser',
      lianxi: '123456789',
    };

    // 模拟从存储中获取项目数据
    uni.getStorage.mockImplementation(({ success }) => {
      success({ data: projectData });
    });

    const vm = {
      projectData: null,
      loading: false,
      realname: '',
      identity: '',
      academy: '',
      onLoad() {
        // 加载项目数据并获取用户信息
        uni.getStorage({
          key: 'projectData',
          success: (res) => {
            this.projectData = res.data;
            this.getUserData();
          },
          fail: () => {
            console.log('没有找到项目数据');
          },
        });
      },
      getUserData: jest.fn(),
    };

    vm.onLoad();
    expect(vm.projectData).toEqual(projectData); // 检查项目数据是否正确加载
    expect(vm.getUserData).toHaveBeenCalled(); // 检查获取用户信息的函数是否被调用
  });

  it('应该根据项目用户名获取用户数据', async () => {
    const userData = {
      realname: '测试用户',
      academy: '测试学院',
      identity: '学生',
    };

    // 模拟云函数返回用户数据
    uniCloud.callFunction.mockResolvedValue({
      result: { code: 200, data: userData },
    });

    const vm = {
      projectData: { username: 'testuser' },
      loading: false,
      realname: '',
      identity: '',
      academy: '',
      getUserData: async function() {
        this.loading = true; // 设置加载状态为 true
        try {
          const res = await uniCloud.callFunction({
            name: 'getdetailbyusername',
            data: { username: this.projectData.username },
          });

          if (res.result.code === 200 && res.result.data) {
            const userData = res.result.data;
            this.realname = userData.realname;
            this.academy = userData.academy;
            this.identity = userData.identity;
          } else {
            console.error('获取用户信息失败', res.result.message);
          }
        } catch (error) {
          console.error('调用云函数失败', error);
        } finally {
          this.loading = false; // 完成加载
        }
      },
    };

    await vm.getUserData();
    expect(vm.realname).toEqual(userData.realname); // 检查真实姓名是否正确
    expect(vm.academy).toEqual(userData.academy); // 检查学院是否正确
    expect(vm.identity).toEqual(userData.identity); // 检查身份是否正确
  });

  it('应该在获取用户信息失败时输出错误信息', async () => {
    // 模拟云函数返回错误信息
    uniCloud.callFunction.mockResolvedValue({
      result: { code: 400, message: '用户不存在' },
    });

    const vm = {
      projectData: { username: 'testuser' },
      loading: false,
      getUserData: async function() {
        this.loading = true; // 设置加载状态为 true
        try {
          await uniCloud.callFunction({
            name: 'getdetailbyusername',
            data: { username: this.projectData.username },
          });
        } catch (error) {
          console.error('调用云函数失败', error);
        } finally {
          this.loading = false; // 完成加载
        }
      },
    };

    await vm.getUserData();
    // 这里可以添加对控制台输出的检查,例如使用 spy 来确认 console.error 被调用
  });

  it('应该在点击返回按钮时返回上一页', () => {
    const vm = {
      goBack() {
        uni.navigateBack({
          delta: 1,
        });
      },
    };

    vm.goBack();
    expect(uni.navigateBack).toHaveBeenCalledWith({ delta: 1 }); // 检查返回操作是否被调用
  });
});

测试的几个函数与思路(与代码中的测试一一对应)

项目数据加载:测试在 onLoad 中是否正确加载了项目数据(在详情页面可能会出现没有数据的情况,原因之一是onload函数中的getStorage函数或者是getUserdata函数调用失败)。
用户数据获取:测试从云函数获取用户数据是否正常工作,并验证正确的属性被设置。(获取的用户数据可能结构不对,与传入数据库的数据结构有关)
错误处理:模拟云函数调用失败,确保程序能妥善处理错误。(在某些情况下云函数可能调用失败)
加载状态:测试在获取用户数据时,加载状态是否正确设置。(加载状态会影响详情页面的显示)
导航功能:验证返回按钮的功能是否正常。(返回功能失败会导致界面不能正常跳转)

测试工具

HBuilderX uni-app自动化测试插件插件地址 要想进行单元测试 首先你应该配置好相应的环境,配置好环境之后,你就要学会编写单元测试代码 在此过程中 你可以询问chapgpt有关教程,要弄清编写单元测试的意义在哪,也就是这个核心函数或功能可能会遇到哪些情况,在此基础上继续思考可能出现的极端情况,并且最重要的一点,要搞起对应代码的核心逻辑,这也就是为什么单元测试最好由自己来编写,在梳理清楚要测试的代码逻辑后编写单元测试能顺利不少。

如何应对未来开发人员的***难

只能是尽量多学,多写代码,在不断地实践中熟悉各种各样可能会出现的情况,同时在书写代码的时候注意逻辑性,逻辑的严谨也有助于减少某些极端情况的产生。

8.Github的代码签入记录截图

9.遇到的代码模块异常或结对困难及解决方法


1.代码逻辑异常问题:this.getUserData()一开始没有放在success: (res)里,而是写在uni.getStorage()的下面,导致在username还没获取到时,getUserdata就开始运行导致获取不到项目数据,后来通过将项目数据具体化和console.log打印信息,梳理代码结构,发现并解决了这个问题。
2.结对困难问题:github文件上传后的合并处理,一开始经常出现合并文件冲突问题,后来通过更加频繁的交流以及详细的记录修改的所属文件,大大减少了合并冲突问题。

10.评价队友

黄森福
值得学习的地方:在项目开发合作过程中我的队友积极沟通,能够了解对方的开发进度,行动力强,自学能力强,对相关工具应用熟练,与其团队配合非常顺利。

posted @ 2024-10-10 22:02  刚下雨  阅读(15)  评论(0编辑  收藏  举报