Nếu tôi có một phương thức tự gọi theo một điều kiện nhất định, có thể viết một bài kiểm tra để xác minh hành vi không? Tôi rất muốn xem một ví dụ, tôi không quan tâm đến khuôn khổ giả hoặc ngôn ngữ. Tôi đang sử dụng RhinoMocks trong C# vì vậy tôi tò mò nếu nó là một tính năng thiếu của khuôn khổ, hoặc nếu tôi hiểu lầm một cái gì đó cơ bản, hoặc nếu nó chỉ là một impossibility.Làm thế nào để viết một bài kiểm tra Mockist của một phương pháp đệ quy
Trả lời
Giả sử bạn muốn làm một cái gì đó giống như lấy tên tập tin từ một đường dẫn đầy đủ, ví dụ:
c:/windows/awesome/lol.cs -> lol.cs
c:/windows/awesome/yeah/lol.cs -> lol.cs
lol.cs -> lol.cs
và bạn có:
public getFilename(String original) {
var stripped = original;
while(hasSlashes(stripped)) {
stripped = stripped.substringAfterFirstSlash();
}
return stripped;
}
và bạn muốn viết:
public getFilename(String original) {
if(hasSlashes(original)) {
return getFilename(original.substringAfterFirstSlash());
}
return original;
}
Đệ quy ở đây là chi tiết triển khai và không được kiểm tra. Bạn thực sự muốn có thể chuyển đổi giữa hai triển khai và xác minh rằng chúng tạo ra cùng một kết quả: cả hai đều tạo ra lol.cs cho ba ví dụ trên. Điều đó đang được nói, bởi vì bạn đang đệ quy theo tên, thay vì nói điều nàyMethod.again() vv, trong Ruby bạn có thể bí danh phương thức gốc thành một tên mới, xác định lại phương thức với tên cũ, gọi hàm mới và kiểm tra xem bạn có kết thúc bằng phương thức mới được xác định hay không.
def blah
puts "in blah"
blah
end
alias blah2 blah
def blah
puts "new blah"
end
blah2
Bạn có nói rằng trong trường hợp này, một bài kiểm tra đơn vị xác minh trạng thái của phương pháp là đủ tốt? – JeremyWeir
xin lỗi, tôi không hiểu rõ câu hỏi của bạn. Trong ví dụ đường dẫn tệp của tôi, kiểm tra đơn vị xác minh đầu ra của phương thức là đủ hoặc thậm chí tốt hơn so với phương thức xác minh đệ quy. Tuy nhiên, tôi không biết tình huống cụ thể của bạn, vì vậy nó có thể khác. – miaubiz
@jayrdub - Trong xác minh nhà nước nói chung là chính xác những gì bạn muốn thử nghiệm đơn vị của bạn để làm. Kiểm tra giá trị trả về của phương thức và/hoặc các thuộc tính công khai của đối tượng đang được kiểm tra. Mọi thứ khác là chi tiết triển khai và có thể thay đổi trong khi tái cấu trúc. – TrueWill
Không có gì để giám sát độ sâu ngăn xếp/số lượng các cuộc gọi hàm (đệ quy) trong bất kỳ khung mocking nào mà tôi biết. Tuy nhiên, đơn vị kiểm tra rằng các điều kiện trước giả lập thích hợp cung cấp các đầu ra chính xác phải giống như mô phỏng một hàm không đệ quy.
Đệ quy đệ quy dẫn đến tràn ngăn xếp, bạn sẽ phải gỡ lỗi riêng biệt, nhưng kiểm tra đơn vị và mocks chưa bao giờ loại bỏ nhu cầu đó ngay từ đầu.
một phương pháp mà các cuộc gọi riêng của mình dưới một điều kiện nhất định, là nó có thể viết một bài kiểm tra để xác minh hành vi?
Có. Tuy nhiên, nếu bạn cần kiểm tra đệ quy, bạn tốt hơn tách điểm vào vào đệ quy và bước đệ quy cho mục đích thử nghiệm.
Dù sao, đây là ví dụ về cách kiểm tra nếu bạn không thể làm điều đó. Bạn không thực sự cần bất kỳ chế nhạo nào:
// Class under test
public class Factorial
{
public virtual int Calculate(int number)
{
if (number < 2)
return 1
return Calculate(number-1) * number;
}
}
// The helper class to test the recursion
public class FactorialTester : Factorial
{
public int NumberOfCalls { get; set; }
public override int Calculate(int number)
{
NumberOfCalls++;
return base.Calculate(number)
}
}
// Testing
[Test]
public void IsCalledAtLeastOnce()
{
var tester = new FactorialTester();
tester.Calculate(1);
Assert.GreaterOrEqual(1, tester.NumberOfCalls );
}
[Test]
public void IsCalled3TimesForNumber3()
{
var tester = new FactorialTester();
tester.Calculate(3);
Assert.AreEqual(3, tester.NumberOfCalls );
}
Bạn hiểu nhầm mục đích của các đối tượng giả. Mocks (theo nghĩa Mockist) được sử dụng để kiểm tra tương tác hành vi với các phụ thuộc của hệ thống đang được kiểm tra.
Vì vậy, ví dụ, bạn có thể có một cái gì đó như thế này:
interface IMailOrder
{
void OrderExplosives();
}
class Coyote
{
public Coyote(IMailOrder mailOrder) {}
public void CatchDinner() {}
}
Coyote phụ thuộc vào IMailOrder. Trong mã sản xuất, một thể hiện của Coyote sẽ được thông qua một thể hiện của Acme, thực hiện IMailOrder. (Điều này có thể được thực hiện thông qua tính năng Chèn phụ thuộc thủ công hoặc thông qua khung DI.)
Bạn muốn thử phương thức CatchDinner và xác minh rằng phương thức đó gọi OrderExplosives.Để làm như vậy, bạn:
- Tạo đối tượng giả để triển khai IMailOrder và tạo một thể hiện của Coyote (hệ thống đang thử nghiệm) bằng cách truyền đối tượng giả cho công cụ xây dựng của nó. (Sắp xếp)
- Gọi CatchDinner. (Act)
- Yêu cầu đối tượng giả để xác minh rằng một kỳ vọng nhất định (OrderExplosives được gọi) đã được đáp ứng. (Assert)
Khi bạn thiết lập các kỳ vọng trên đối tượng giả có thể phụ thuộc vào khuôn mẫu mô phỏng (cách ly) của bạn.
Nếu lớp hoặc phương pháp bạn đang thử nghiệm không có phụ thuộc bên ngoài, bạn không cần (hoặc muốn) sử dụng các đối tượng giả cho tập hợp thử nghiệm đó. Nó không quan trọng nếu phương pháp này là đệ quy hay không.
Bạn thường muốn kiểm tra các điều kiện biên, vì vậy bạn có thể kiểm tra cuộc gọi không nên đệ quy, một cuộc gọi với một cuộc gọi đệ quy duy nhất và một cuộc gọi đệ quy sâu sắc. (miaubiz có một điểm tốt về đệ quy là một chi tiết thực hiện, mặc dù.)
EDIT: Bằng cách "gọi" trong đoạn cuối tôi có nghĩa là một cuộc gọi với các thông số hoặc trạng thái đối tượng sẽ kích hoạt độ sâu đệ quy nhất định. Tôi cũng khuyên bạn nên đọc The Art of Unit Testing.
EDIT 2: Ví dụ kiểm tra mã sử dụng Moq:
var mockMailOrder = new Mock<IMailOrder>();
var wily = new Coyote(mockMailOrder.Object);
wily.CatchDinner();
mockMailOrder.Verify(x => x.OrderExplosives());
"Nếu lớp hoặc phương pháp bạn đang thử nghiệm không có phụ thuộc bên ngoài, bạn không cần (hoặc muốn) sử dụng các đối tượng mô phỏng cho tập hợp các phép thử đó. Cho dù phương pháp này có đệ quy hay không." Đó là phần tôi cần được nhắc nhở, cảm ơn. Tôi thích câu trả lời của bạn tốt nhất nhưng nó tự động chọn trước khi tôi có thể. – JeremyWeir
@jayrdub - Cảm ơn! :) – TrueWill
Dưới đây là 'nông dân' cách tiếp cận của tôi (trong Python, kiểm tra, xem các ý kiến cho các lý do)
Lưu ý rằng việc thực hiện chi tiết "tiếp xúc" nằm ngoài câu hỏi ở đây, vì những gì bạn đang thử nghiệm là kiến trúc cơ bản được sử dụng bởi mã "cấp cao nhất". Vì vậy, thử nghiệm nó là hợp pháp và cư xử tốt (tôi cũng hy vọng, đó là những gì bạn có trong tâm trí).
Mã này (ý tưởng chính là để đi từ một hàm đệ quy đơn nhưng "untestable" để một cặp tương đương với chức năng đệ quy phụ thuộc (và do đó kiểm chứng)):
def factorial(n):
"""Everyone knows this functions contract:)
Internally designed to use 'factorial_impl' (hence recursion)."""
return factorial_impl(n, factorial_impl)
def factorial_impl(n, fct=factorial):
"""This function's contract is
to return 'n*fct(n-1)' for n > 1, or '1' otherwise.
'fct' must be a function both taking and returning 'int'"""
return n*fct(n - 1) if n > 1 else 1
Bài kiểm tra:
import unittest
class TestFactorial(unittest.TestCase):
def test_impl(self):
"""Test the 'factorial_impl' function,
'wiring' it to a specially constructed 'fct'"""
def fct(n):
"""To be 'injected'
as a 'factorial_impl''s 'fct' parameter"""
# Use a simple number, which will 'show' itself
# in the 'factorial_impl' return value.
return 100
# Here we must get '1'.
self.assertEqual(factorial_impl(1, fct), 1)
# Here we must get 'n*100', note the ease of testing:)
self.assertEqual(factorial_impl(2, fct), 2*100)
self.assertEqual(factorial_impl(3, fct), 3*100)
def test(self):
"""Test the 'factorial' function"""
self.assertEqual(factorial(1), 1)
self.assertEqual(factorial(2), 2)
self.assertEqual(factorial(3), 6)
sản lượng:
Finding files...
['...py'] ... done
Importing test modules ... done.
Test the 'factorial' function ... ok
Test the 'factorial_impl' function, ... ok
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
- 1. Rspec: Làm thế nào để kiểm tra đệ quy?
- 2. Làm thế nào để viết một trình phân tích cú pháp gốc đệ quy từ đầu?
- 3. TDD - viết bài kiểm tra cho một phương pháp lặp/làm việc với các bộ sưu tập
- 4. Làm cách nào để viết một bài kiểm tra RSpec cho một phương thức Ruby có chứa "gets.chomp"?
- 5. Làm thế nào để viết một bài kiểm tra đơn vị?
- 6. Làm thế nào để viết bài kiểm tra đơn vị kiểm tra bất biến đồng thời
- 7. Làm thế nào để đơn vị kiểm tra một phương pháp với loại trả về void?
- 8. Làm thế nào để moq một NetworkStream trong một bài kiểm tra đơn vị?
- 9. Làm thế nào để kiểm tra mã nguồn của một phương pháp python?
- 10. Làm thế nào để bạn biết những gì để kiểm tra khi viết bài kiểm tra đơn vị?
- 11. Làm thế nào để viết một bài kiểm tra đơn vị cho "T phải là một kiểu tham chiếu"?
- 12. Làm thế nào để tạo ra bài kiểm tra cho một phương pháp mới bằng cách sử dụng IDEA?
- 13. Làm thế nào để viết các bài kiểm tra đơn vị đa luồng?
- 14. Làm cách nào để viết một bài kiểm tra để xử lý ngoại lệ dự kiến?
- 15. Làm thế nào để viết một bài kiểm tra đơn vị để bao gồm trường hợp một IOException được ném?
- 16. Làm thế nào để viết một bài kiểm tra dự kiến một lỗi sẽ được ném vào Jasmine?
- 17. Làm thế nào để viết một bài kiểm tra Jasmine cho một trang web có HTML và JavaScript hoặc jQuery?
- 18. Đệ quy giữa các phương thức khác nhau của cùng một phương pháp
- 19. Làm thế nào để kiểm tra xem phương pháp có một thuộc tính
- 20. Kiểm tra Ngoại lệ của một phương pháp với EasyMock
- 21. Big O của các phương pháp đệ quy
- 22. Làm thế nào để kiểm tra nếu một phương pháp tồn tại lúc chạy trong Java?
- 23. Làm thế nào để kiểm tra phương pháp void với các công cụ kiểm tra Junit?
- 24. Làm thế nào để bạn kiểm tra hàm băm params trong bài kiểm tra Rails?
- 25. Tạo IL cho đệ quy phương pháp
- 26. Làm thế nào để xác định xem một phương pháp là một trường hợp chung của một phương pháp chung
- 27. Làm thế nào để sử dụng Moq để kiểm tra một phương pháp không có giá trị trả về?
- 28. làm thế nào để viết một php để có được bài đăng json từ một webhook?
- 29. Sử dụng phương pháp đệ quy trong java
- 30. Mới để thử nghiệm đơn vị, làm thế nào để viết các bài kiểm tra tuyệt vời?
Nó không rõ ràng với tôi. Chính xác những gì đang cố gắng thử nghiệm? Đó là phương pháp tự gọi mình "trong điều kiện nhất định" (rằng "ngăn xếp cuộc gọi" sẽ theo một con đường nhất định "trong điều kiện nhất định") hoặc cái gì khác? – Ando