【和ChatGPT对话】在解答函数和API实现之间反复横跳 - 容易忘事的一次性选手

时间:2023-02-22 16:02:57

前言和小结

在之前的对话中,ChatGPT 表现了出色的能力,也表现了混乱的思维。本篇文章就来探索一下出色和混乱的边界。 用例:我们给出一个数学函数,要求 ChatGPT 编写api实现和测试用例。 结论: 1、遇到一个清晰明了的问题时,ChatGPT 能够一次解答并表现出色。无论是解答数学函数,还是编写API,ChatGPT 都可以。 2、如果问题中关联别的问题,ChatGPT 就难以完美完成,如果再指出几处错误,ChatGPT 甚至会丢失记忆,把要求当作一个新问题开始求解。这在之前的对话中有类似现象。本次会话中还出现卡顿现象(重复一句代码),之前并没有碰到过。 对于写作来说,这种含蓄可能会带来无穷的灵感。但对于科学技术来说,不严谨的表述还不能投入使用,ChatGPT 还有一段路要走。

解答数学函数

示例函数为 c = (a+b)/(a-b) + a*b

【和ChatGPT对话】在解答函数和API实现之间反复横跳 - 容易忘事的一次性选手

【和ChatGPT对话】在解答函数和API实现之间反复横跳 - 容易忘事的一次性选手

【和ChatGPT对话】在解答函数和API实现之间反复横跳 - 容易忘事的一次性选手


我们可以看到,ChatGPT 三次计算都正确,可以证明其具备正确解答的能力。

编写API

我们先给出一个简单功能,输出当前时间,要求实现,编写测试用例。

【和ChatGPT对话】在解答函数和API实现之间反复横跳 - 容易忘事的一次性选手

【和ChatGPT对话】在解答函数和API实现之间反复横跳 - 容易忘事的一次性选手

从以上代码可以看出,开发的基本功能是没有问题的。

编写API解决数学问题

Q1 现有函数 y = (a+b)/(a-b)+a*b,a, b 为任意数值,值存在无法计算的情况。编写 spring boot api 实现,api path 为 /api/calc/ab,数据类型使用decimal,不要抛出异常,并编写单元测试用例

以下是一个可能的实现:


import java.math.BigDecimal;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CalculatorController {
    
    @GetMapping("/api/calc/ab")
    public ResponseEntity<BigDecimal> calculate(@RequestParam(required = false) BigDecimal a, @RequestParam(required = false) BigDecimal b) {
        if (a == null || b == null || a.compareTo(b) == 0) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
        }
        
        BigDecimal numerator = a.add(b);
        BigDecimal denominator = a.subtract(b);
        if (denominator.compareTo(BigDecimal.ZERO) == 0) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
        }
        
        BigDecimal result = numerator.divide(denominator, 2, BigDecimal.ROUND_HALF_UP).add(a.multiply(b));
        return ResponseEntity.ok(result);
    }
}

上述实现首先检查了参数 a 和 b 是否为空或者相等,如果是则返回 400 Bad Request。然后通过 BigDecimal 类计算分子和分母,并检查分母是否为零。最后,使用 BigDecimal 的 divide() 方法计算结果,同时加上 a * b。最后返回 ResponseEntity 对象,包含 HTTP 状态码和计算结果。

以下是一个可能的单元测试:

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import java.math.BigDecimal;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import org.springframework.test.web.servlet.result.MockMvc

居然结巴了,一直重复一句话。

Q2 重新编写测试用例

以下是一个可能的测试用例:

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import java.math.BigDecimal;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;

@WebMvcTest(CalculatorController.class)
public class CalculatorControllerTest {
    
    @Autowired
    private MockMvc mockMvc;
    
    @MockBean
    private CalculatorService calculatorService;
    
    @Test
    public void testCalculate() throws Exception {
        when(calculatorService.calculate(any(BigDecimal.class), any(BigDecimal.class)))
            .thenReturn(BigDecimal.valueOf(3.5));
        
        mockMvc.perform(MockMvcRequestBuilders.get("/api/calc/ab")
            .param("a", "2.0")
            .param("b", "0.5")
            .contentType(MediaType.APPLICATION_JSON))
            .andExpect(MockMvcResultMatchers.status().isOk())
            .andExpect(MockMvcResultMatchers.content().string("3.5"))
            .andDo(MockMvcResultHandlers.print());
    }
    
    @Test
    public void testCalculateWithNullA() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/api/calc/ab")
            .param("b", "0.5")
            .contentType(MediaType.APPLICATION_JSON))
            .andExpect(MockMvcResultMatchers.status().isBadRequest())
            .andDo(MockMvcResultHandlers.print());
    }
    
    @Test
    public void testCalculateWithNullB() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/api/calc/ab")
            .param("a", "2.0")
            .contentType(MediaType.APPLICATION_JSON))
            .andExpect(MockMvcResultMatchers.status().isBadRequest())
            .andDo(MockMvcResultHandlers.print());
    }
    
    @Test
    public void testCalculateWithEqualAB() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/api/calc/ab")
            .param("a", "2.0")
            .param("b", "2.0")
            .contentType(MediaType.APPLICATION_JSON))
            .andExpect(MockMvcResultMatchers.status().isBadRequest())
            .andDo(MockMvcResultHandlers.print());
    }
}

这个测试用例使用了 Spring Boot Test 框架和 Mockito 模拟框架。首先,通过 MockBean 注解注入一个名为 calculatorService 的 Mock 对象。然后,编写了四个测试方法:

testCalculate:测试正常情况下的计算结果,参数 a 和 b 分别为 2.0 和 0.5。 testCalculateWithNullA:测试当参数 a 为空时的情况。 testCalculateWithNullB:测试当参数 b 为空时的情况。 testCalculateWithEqualAB:测试当参数 a 和 b 相等时的情况。 每个测试方法中,使用 MockMvcRequestBuilders 构造 GET 请求,并通过 MockMvc 对象执行请求。其中,testCalculate 方法使用了 when 和 thenReturn 方法模拟了 calculatorService 的行为,返回了一个值为 3.5
显然,2.0 和 0.5 计算不出 3.5。

其他尝试

【和ChatGPT对话】在解答函数和API实现之间反复横跳 - 容易忘事的一次性选手

【和ChatGPT对话】在解答函数和API实现之间反复横跳 - 容易忘事的一次性选手

【和ChatGPT对话】在解答函数和API实现之间反复横跳 - 容易忘事的一次性选手