1 điểm bởi GN⁺ 2024-02-25 | 1 bình luận | Chia sẻ qua WhatsApp

Trình tạo kiểm thử mới dựa trên LLM của Meta cho thấy tương lai của phát triển phần mềm

  • Meta đã công bố bài báo "Automated Unit Test Improvement using Large Language Models at Meta".
  • Bài báo này cho thấy cách dùng AI để tăng tốc độ phát triển và giảm lỗi phần mềm.
  • Bằng cách tích hợp LLM vào quy trình làm việc của lập trình viên, hệ thống đề xuất các cải tiến phần mềm chính xác và đầy đủ nhằm cải thiện độ bao phủ mã hiện tại.

Các điểm chính

  • TestGen-LLM sử dụng cách tiếp cận 'Assured LLM-based Software Engineering' (Assured LLMSE).
  • Hệ thống dùng phương pháp tổ hợp, tạo ra các phương án cải tiến mã bằng nhiều LLM, prompt và siêu tham số, rồi chọn ra phương án tốt nhất.
  • TestGen-LLM được thiết kế đặc biệt để cải thiện các bài kiểm thử hiện có do con người viết.

Thống kê

  • Trong đánh giá sản phẩm Reels và Stories của Instagram, 75% các ca kiểm thử do TestGen-LLM tạo ra đã build thành công, 57% vượt qua một cách ổn định và 25% làm tăng độ bao phủ.
  • TestGen-LLM có thể cải thiện 10% tổng số lớp đã được áp dụng, và các lập trình viên đã chấp nhận 73% đề xuất cải tiến kiểm thử để đưa vào production.
  • Trong "test-a-thon" nơi các kỹ sư Meta tạo kiểm thử để tăng độ bao phủ kiểm thử của Instagram, số dòng mã trung vị được các bài kiểm thử TestGen-LLM bổ sung là 2,5.

Insight có thể áp dụng

  • Đây là một ví dụ tốt cho thấy có thể dùng LLM để cải thiện hiệu quả năng suất phát triển và độ tin cậy phần mềm.
  • Giá trị thực sự của LLM nằm ở khả năng tìm ra và bắt được các edge case ngoài dự kiến.
  • Để dùng LLM trong production, cần có orchestration, pipeline và xử lý phù hợp.

Cách TestGen-LLM hoạt động

  • TestGen-LLM áp dụng một loạt bộ lọc ngữ nghĩa lên các lời giải ứng viên được tạo bởi LLM nội bộ của Meta để chỉ giữ lại những bài kiểm thử có giá trị nhất.
  • Bộ lọc 1: khả năng build, bộ lọc 2: thực thi (kiểm thử có pass hay không), bộ lọc 3: tính thất thường, bộ lọc 4: cải thiện độ bao phủ.
  • Các bộ lọc xử lý này bảo đảm việc cải thiện test suite.

Kết luận

  • Bài báo này là một cách tốt để theo dõi tiến bộ của LLM trong không gian độ tin cậy phần mềm, nơi nhiều lập trình viên đã sử dụng LLM.
  • LLM sẽ ngày càng có khả năng tìm lỗi và kiểm thử trong các hệ thống phần mềm phức tạp hơn.

Ý kiến của GN⁺

  • Bài viết này mang đến góc nhìn thú vị về cách trí tuệ nhân tạo có thể ảnh hưởng đến tương lai của phát triển phần mềm.
  • Các công cụ như TestGen-LLM có thể hỗ trợ rất nhiều trong việc tự động hóa công việc của lập trình viên và nâng cao hiệu quả.
  • Sự phát triển của các công nghệ này đang hướng tới việc giảm độ phức tạp của phát triển phần mềm, nâng cao chất lượng và tiết kiệm thời gian cho lập trình viên.

1 bình luận

 
GN⁺ 2024-02-25
Ý kiến trên Hacker News
  • Thật thú vị khi thấy xu hướng muốn dùng LLM cho việc viết mã kiểm thử trước cả triển khai
    Có lẽ vì đã làm TDD quá nhiều, tôi cho rằng kiểm thử là thứ mô tả hệ thống nên hoạt động như thế nào, và phần này nên do con người định nghĩa. Mã nguồn phải được đặt vừa trong các lan can do kiểm thử tạo ra
    Tuy vậy, LLM có thể hữu ích trong việc chỉ ra những vùng còn thiếu đặc tả. Việc yêu cầu nó đề xuất unit test cho các phần chưa được đặc tả đầy đủ có thể chính là điều đang diễn ra ở đây
    Ngay cả trước thời LLM, đôi khi tôi cũng nghĩ nếu đã viết sẵn toàn bộ kiểm thử thì liệu một con khỉ gõ bàn phím có thể tạo ra ứng dụng không

    • Trong các codebase legacy, người ta thường tạo kiểm thử đặc tính (characterisation tests)
      Đó là các kiểm thử định nghĩa codebase hiện tại thực sự hoạt động ra sao, chứ không phải con người tin rằng mã nên hoạt động như thế nào
      Nhờ đó có thể viết lại, refactor, thiết kế lại trong khi giảm thiểu hồi quy. Vấn đề của nhiều mã legacy là không ai hiểu hành vi dự định là gì, và đôi khi ngay cả người dùng cũng tin rằng nó nên hoạt động khác với hành vi thực tế
      Vì vậy, nếu không phải là thay đổi mong muốn được nêu rõ, điều quan trọng nhất là không thay đổi hành vi
    • Có thể bạn đã biết rồi, nhưng cũng đáng nghĩ đến kiểm thử dựa trên thuộc tính (property-based testing). Hypothesis có lẽ là thứ khiến cách này được biết đến rộng rãi nhất và đáng khuyên dùng, nhưng nó không phải cách tiếp cận duy nhất hay bản triển khai chất lượng cao duy nhất. Cũng từng có thời Haskell QuickCheck lớn đến mức thường xuất hiện trên HN
      Ý tưởng cơ bản là biểu diễn các mệnh đề yếu hơn về hành vi của mã dưới dạng “thuộc tính”, thay vì một hệ thống chứng minh dạng đóng hoàn chỉnh, rồi kiểm chứng chúng trong những giới hạn vốn mang tính xác suất
      Ví dụ tiêu biểu là đảo ngược chuỗi. Nếu đảo ngược một chuỗi hai lần thì thường phải thu được đầu vào ban đầu. Chỉ với một dòng mã, bạn có thể kiểm tra cả những trường hợp biên Unicode kỳ quặc miễn là thời gian và điện cho phép
      Ví dụ nghe có vẻ tầm thường, nhưng tôi đã thấy các cao thủ CUDA từng làm về tự động vi phân — thứ sau này trở thành PyTorch — và kernel sử dụng cách này cực kỳ tốt, đạt độ tin cậy mã cao gấp khoảng 5 lần với một nửa công sức và chi phí
      Không phải lúc nào cũng phù hợp, nhưng khi khớp thì rất tuyệt, và LLM có vẻ có thể tiến khá gần tới các ví dụ Hypothesis hơn là phải bắt đầu từ con số không
    • Viết mã triển khai vui và thú vị hơn nhiều, vì đó là tạo ra thứ ứng dụng thực sự phải làm
      Ngược lại, khi viết kiểm thử, bạn phải mô tả thứ ứng dụng phải làm bằng một ngôn ngữ cực kỳ dài dòng và nhiều ràng buộc, rồi viết hàng chục hoặc hàng trăm dòng mã thiết lập chỉ để đưa vào vài câu if/else được tô vẽ
      Trong các ngôn ngữ như C++ hay Java, unit test được cấu thành từ sự nhàm chán, nên không có gì ngạc nhiên khi nảy sinh bản năng muốn giao việc đó cho LLM
    • Có thể là vì trên thực tế nhiều kỹ sư không giỏi làm kiểm thử
      Tôi đã thấy nhiều kỹ sư viết mã suốt vài ngày rồi sau đó, vì không thể tránh được, mới viết vài kiểm thử để “chứng minh” rằng hệ thống hoạt động. Độ phủ thấp và thường rất dễ vỡ
      Với những kỹ sư suy nghĩ và làm việc theo cách đó, một hệ thống như thế này sẽ trông như món quà trời cho
      Tôi cũng từng có quản lý cấm viết kiểm thử trước vì cho rằng như vậy chậm. May là tôi đang ở dạng biệt phái nên có thể phớt lờ và nói “hãy nói với sếp của tôi”, nhưng có lẽ người đó cũng nghĩ giống các kỹ sư nói trên
      Nhìn theo cách khác, hầu hết lập trình viên ghét tài liệu. Nếu có AI viết tài liệu tuyệt vời từ mã, họ sẽ thích. Và với những lập trình viên như vậy, tài liệu tuyệt vời là tài liệu mà họ không phải tự viết
    • Ngay cả ngoài AI, nhìn cách mã kiểm thử được đối xử cũng cho cảm giác tương tự
      Mã kiểm thử thường bị xem là mã có mức ưu tiên thấp và được giao cho các kỹ sư junior hơn, điều này trông hoàn toàn ngược với hướng mong muốn
  • Tôi không muốn rà soát toàn bộ, nhưng có một phần dường như đặc biệt lệch khá xa
    Với điều kiện là tôi chỉ đọc lướt bài báo gốc ngay sau khi nó được đăng và giờ đang xem lại, nên trí nhớ có thể mơ hồ
    Bài blog viết rằng phần lớn các kiểm thử TestGen-LLM của Meta chỉ phủ thêm 2,5 dòng, nhưng một kiểm thử phủ 1326 dòng, và giá trị của một kiểm thử đó “lớn hơn theo cấp số nhân”, còn LLM có giá trị lớn ở chỗ chủ động suy nghĩ vượt khuôn khổ để bắt các trường hợp biên bất ngờ
    Nhưng ngay cụm “có giá trị hơn theo cấp số nhân” đã nên làm chuông báo nhảm nhí kêu lên. Nhìn vào bài báo, các tác giả mô tả độ phủ 1326 dòng này là một kiểm thử đơn lẻ trúng jackpot, và nói rằng độ phủ dòng bổ sung thực tế có thể kỳ vọng từ một kiểm thử TestGen-LLM đơn lẻ có trung vị là 2,5 dòng
    Các tác giả không nhắc đến “trường hợp biên bất ngờ” hay “suy nghĩ vượt khuôn khổ”. Ngược lại, họ trình bày đây là trường hợp ngoại lệ, có thể do chạm vào một nhánh của câu lệnh switch kinh khủng nào đó, hoặc chỉ là ngẫu nhiên từ cách tính code coverage
    Việc phần “kết quả định tính” cũng không đào sâu thêm vào điểm này là điều đáng chú ý. Diễn giải không chính xác chẳng giúp được ai. Trên internet vốn đã có quá nhiều người giả vờ hiểu thứ mình giả vờ đã đọc

    • Tôi là người viết bài, và ý của tôi không phải là các tác giả bài báo đã nói về “trường hợp biên bất ngờ” hay “suy nghĩ vượt khuôn khổ”
      Tôi đã sửa bài để làm rõ hơn rằng một số diễn giải là ý kiến của tôi
      Bài viết này giống một bài bình luận về ý nghĩa của kết quả trong bài báo hơn là bản tóm tắt bài báo. Dù sao thì Hacker News cũng là nơi để thảo luận mà
      Tuy vậy, tôi vẫn cho rằng phần “có giá trị hơn theo cấp số nhân” là đúng. Việc LLM có thể tình cờ “trúng jackpot” về mặt độ phủ kiểm thử chính là cốt lõi của giá trị
      Nếu cứ thử nhiều tổ hợp khác nhau và chỉ cần trúng một jackpot như trong bài báo, điều đó đã rất có giá trị với đội ngũ. Đó có thể là một kiểm thử không rõ ràng hoặc quá nhàm chán để con người tự viết
      Từ góc nhìn của một người từng tốn quá nhiều thời gian chỉ để tìm ra “kiểm thử như thế nào”, dù đã biết cần kiểm thử cái gì trong codebase Big Tech (F/G), tôi thấy giá trị đó là lớn
    • Cơ chế khuyến khích sản xuất mã của Meta nhìn chung bị sai lệch
      Rõ ràng đội này cũng đang bị đẩy theo số dòng mã và số diff. Rốt cuộc nó sẽ chỉ trở thành một công cụ sinh mã nữa, tạo thêm một núi mã khó debug mà thôi
  • Kiểm thử tốt là việc khó, và coverage không phải lúc nào cũng tốt
    Viết quá nhiều test rất dễ khiến chương trình bị đóng cứng lại, thực chất biến nó thành một chương trình phát hiện thay đổi. Kiểu như: “Bạn đã thay đổi gì đó, tất cả test đều hỏng. Không sao, giờ chỉ cần bảo LLM tạo lại là được! Coverage 100%! Tuyệt vời! Tiến bộ quá!”

    • Đồng ý. Test tốt khó hơn code tốt ít nhất một bậc độ lớn
    • Góc nhìn “chương trình phát hiện thay đổi” khá thú vị. Tôi tò mò vì sao điều đó lại xấu
      Với tôi, đó là cơ hội để xác nhận thay đổi ấy có chủ đích hay không. Nếu không có nó, làm sao biết chương trình có làm đúng việc nó cần làm?
    • Có thể chắc chắn rằng code không có coverage thì có test tệ
      Còn ngoài ra thì phải đọc những test tốt mà năm người khác nghĩ ra. Tất cả chúng ta đều viết test không giỏi, mỗi người chỉ làm theo cách riêng của mình
    • Ở một nơi tôi từng làm có test cho web component: commit snapshot của DOM kỳ vọng rồi kiểm tra component có xuất ra đúng như vậy không
      Sau đó, với mọi thay đổi, lập trình viên tự nhiên bấm nút tạo lại và commit tất cả. Diff thì rất nhiều, nhưng tín hiệu thì đáng ngờ
    • Trọng tâm nằm ở các trường hợp đuôi dài
  • Sau khi từng làm trong ngành bán dẫn, đặc biệt là computational lithography, nơi thiết kế hướng kiểm thử là tiêu chuẩn, tôi thấy lập luận này khó thuyết phục
    Điều đó không có nghĩa là lúc nào cũng phải viết test trước production code. Nhưng test cũng là một phần của code, ngang với các phần khác của codebase, và nhất thiết phải được viết cùng với phần code được kiểm thử
    Phần quan trọng nhất của test là thể hiện ý định của lập trình viên. Bộ test cho thấy code nên được dùng như thế nào, nó làm gì, không làm gì, và được viết nhằm mục đích gì
    Nhờ vậy, khi lập trình viên khác dùng hoặc sửa code đó, họ không phải đi tìm manh mối trong codebase như Sherlock Holmes
    Nếu test không kể được một câu chuyện, thì bạn đang viết test sai cách
    Cho đến khi máy tính có thể đọc được suy nghĩ và hiểu ý định tốt hơn, các bộ sinh dựa trên AI/LLM không thể làm thay việc này
    Tất nhiên, nếu mục tiêu duy nhất của bộ test là nhận dấu tích xanh trong bước kiểm tra trước khi commit và khoe con số coverage đẹp, thì AI có thể nhân đôi năng suất
    Bộ sinh code tự động sẽ giúp bạn viết thêm nhiều code tệ với tốc độ ánh sáng. Nếu có ai phàn nàn rằng code phình to và khó hiểu vì có quá nhiều boilerplate, cứ bảo họ dùng AI xử lý. Vì nó đã hiệu quả với bạn mà
    Tương lai của phát triển phần mềm thật sự trông có vẻ như vậy, nhưng đó không phải tương lai tôi mong đợi

    • Tôi đồng ý với gần như toàn bộ, nhưng tôi nghĩ kiểu test này cũng có chỗ đứng
      Thứ bạn mô tả có vẻ là kiểm thử “phần cốt lõi” của code. Đó là loại test kiêm một phần vai trò tài liệu hóa, xác minh và đảm bảo ổn định
      Các loại test khác như fuzzing mang lại giá trị hoàn toàn khác. Tôi nghĩ test dựa trên AI có thể chiếm một không gian ở phần đuôi của phân phối: rất nhiều test giá trị thấp bị bỏ mặc vì con người không đủ năng lượng và thời gian
      Tôi cũng nhìn nhận tình trạng hiện nay của các công cụ AI như vậy. Chúng là công cụ hỗ trợ nhận thức
      Tôi sẽ khá ngạc nhiên nếu hướng nghiên cứu này không mang lại kết quả đáng kể trong vài năm tới
  • Tôi trích lại, có chỉnh sửa nhẹ, điều đã viết khi chính bài báo được đăng. Bài viết của họ trình bày sai số liệu thống kê
    https://news.ycombinator.com/item?id=39406726
    Phần tóm tắt không khớp với nội dung thực tế của bài báo. Bản tóm tắt khiến người ta đọc như thể đó là tỷ lệ theo từng test case: “75% build đúng, 57% pass ổn định, 25% tăng coverage”
    Báo cáo thực tế nói theo test class, và mỗi class có một hoặc nhiều test case
    Nghĩa là: “75% test class có ít nhất một test case mới build đúng”, “57% test class có ít nhất một test case build đúng và pass ổn định”, “25% test class có ít nhất một test case build được, pass được và tăng line coverage so với các test class khác của cùng build target”
    Hai cách nói này là hai câu hoàn toàn khác nhau. Thậm chí còn có chú thích rằng mỗi lần thử mở rộng một test class có thể bao gồm nhiều lần thử sinh test case, nên tỷ lệ thành công trên mỗi test case thường thấp hơn nhiều so với tỷ lệ thành công trên mỗi test class
    Vậy mà trong phần kết luận, họ lại trình bày sai kết quả như trong phần tóm tắt. Họ viết rằng khi dùng TestGen-LLM ở chế độ thử nghiệm, tỷ lệ thành công trên mỗi test case là 25%, và nếu nới lỏng yêu cầu line coverage, chỉ yêu cầu build và pass, thì tỷ lệ thành công tăng lên 57%

  • Tôi thấy đồng cảm với những người sau này sẽ phải bảo trì đống code legacy LLM tệ hại này
    Nó sẽ rất khó coi

    • Tất nhiên là rồi người ta sẽ dùng LLM để bảo trì nó
    • Vậy thì LLM đang tạo việc làm hơn là xóa việc làm. Chỉ là có lẽ không phải những công việc thú vị cho lắm
    • Tôi nghĩ nó cũng không tệ hơn code kiểu enterprise đâu
      Thậm chí có thể trông khá giống, còn chú thích và tài liệu thì đầy đủ hơn, và có thể ít khả năng sai một cách chủ động hơn
    • Xóa test đi là giải quyết xong vấn đề. Dashboard CI cũng sẽ hiện dấu tích xanh
    • Đồng ý
      LLM tuyệt đối sẽ không bao giờ tốt hơn hiện tại và trong 2 năm qua chẳng hề tiến bộ chút nào. Nó chỉ là một chuỗi Markov hào nhoáng
      Nó chỉ có thể dùng để viết code khi một người không biết lập trình mù quáng commit code lên production mà không review gì cả
      Với người biết lập trình thì không đời nào hữu ích, cũng không thể tăng năng suất
      Tôi sẽ phớt lờ mớ nhảm nhí LLM này, thứ sẽ chẳng thay đổi thế giới chút nào, và bạn nhất định cũng nên làm vậy
  • Nếu không tách bạch tốt, rất dễ biến thành một môi trường thù địch với lập trình viên, nơi một quản lý thiếu hiểu biết đòi độ phủ cao và các junior đầy nhiệt huyết lén nhét vào hàng loạt bài test AI
    Cuối cùng, mỗi lần nộp công việc, bạn phải được đóng dấu thông qua từ đống mã test do LLM tạo ra nhưng khó bảo trì
    Việc viết một số test có thể nhanh hơn, nhưng không có gì đảm bảo việc bảo trì sẽ nhanh hơn. Việc bảo trì mã được test cũng vậy. Vì không có gì đảm bảo rằng các test tốt sẽ được tạo ra
    Quá trình vật lộn khi viết test thường cũng giúp lập trình viên kiểm tra thiết kế từ sớm. Nếu khó test thì thường không phải là thiết kế tốt; chẳng hạn trong bối cảnh phải viết mã cùng người khác, hợp đồng của component thường chưa được trừu tượng hóa đủ
    Một điểm dễ bị bỏ sót là test là mã có thể hy sinh. Phần lớn test sẽ không bắt được gì trong suốt vòng đời của chúng, và điều đó vẫn ổn. Vì chúng mang lại sự yên tâm tự động và khi có lỗi thì giúp thu hẹp các manh mối sai
    Nhưng đầu tư tối đa vào một cơ chế an toàn mang tính xác suất không phải lúc nào cũng đem lại phần thưởng. Khi độ phủ càng gần mức trần, lợi ích biên càng giảm. Nếu không phải là các đường thực thi có lưu lượng cao như thư viện chuẩn, thì việc khoe độ phủ cao thường không được đền đáp
    Hơn nữa, gần như luôn cần có cả một hệ sinh thái test gồm không chỉ unit test mà còn integration test, system test, v.v. thì toàn bộ mới vận hành được. Liệu LLM có ngồi trong các cuộc họp thiết kế, hiểu kiến trúc rồi viết cả những test đó không? Hay nó sẽ phóng đại những gì mình có thể làm và đẩy lùi những việc cần làm?
    Khi đầu tư công sức vào test, cần có cảm giác phán đoán “điều gì là liên quan” không chỉ tại thời điểm viết mà cả trong thiết kế và bảo trì. Con người làm việc này khá tốt, còn công cụ AI thì không
    Phần LLM có thể tiết kiệm thời gian là các phím gõ của lập trình viên giàu kinh nghiệm, người đã có cảm giác sẵn về cái gì nên test và cái gì không. Đồng thời, nó cũng có thể gây cản trở bằng cách lén đưa vào mã những thứ không mấy liên quan, và thực tế đã từng như vậy
    Tôi không muốn một nền kinh tế sản xuất phím gõ. Tôi muốn một tập hợp các phím gõ được suy nghĩ kỹ và có mức độ liên quan cao. Và tôi hy vọng vế sau được tách biệt rõ khỏi vế trước, để theo thời gian, tính hữu dụng khách quan hoặc sự thiếu vắng của nó được bộc lộ

  • Tôi đã thử bằng GPT-4 rồi
    Tôi đưa cho nó một module TypeScript và yêu cầu tạo unit test, nó đã tạo ra các test chạy được, bao phủ không chỉ luồng bình thường mà cả một số trường hợp biên

    • Tôi không hiểu lắm vì sao các bình luận tương tự lại bị downvote
      ChatGPT làm tốt hơn kỳ vọng ở nhiều mặt. Test có vẻ là việc dễ theo tiêu chuẩn năng lực của GPT
      Tuần trước tôi còn bắt nó viết mã Python duyệt AST để tạo graph và component React Flow. Tôi không sửa gì cả, chỉ lặp lại phản hồi qua prompt vài lần, và nó chạy rất tốt. Tôi đã thấy nhiều năng lực thú vị tương tự ở GPT
  • AI biết phải viết test nào bằng cách nào?
    Đây là một thử nghiệm thú vị, nhưng cũng hơi đáng nghi. Tôi nghĩ cách AI có thể hỗ trợ tốt nhất trong phát triển phần mềm là khi lập trình viên đặt câu hỏi về mã của mình hoặc mã của người khác, AI trả lời. Đôi khi có thể kèm theo đề xuất mã, nhưng không nhất thiết lúc nào cũng phải vậy
    Nó cần có khả năng trả lời những câu hỏi như “Có cách nào đơn giản hóa đoạn mã này không?”, “Những input nào có thể gây lỗi?”
    AI nên giúp chúng ta hiểu mã và hiểu cách cải thiện nó. Nếu chúng ta không nói cho AI biết phải làm gì, nó không thể biết chúng ta muốn gì, nên không nên để nó tự viết tất cả
    Test là một ví dụ tốt. Chúng ta muốn test điều gì?

  • Cuối cùng cũng đã có AI code generation khiến tôi thấy thuyết phục