2010-09-29 36 views
13

Tôi đang sử dụng JUnit4 và Hibernate3 trong dự án của mình. Hibernate phụ thuộc vào Slf4j và do đó dự án của tôi cũng bao gồm thư viện này. Bây giờ tôi muốn sử dụng Slf4j trong các bài kiểm tra đơn vị để đăng nhập thông tin kiểm tra bổ sung. Bạn có thể vui lòng cung cấp một ví dụ ngắn về cách kiểm tra đơn vị của tôi sẽ trông như thế nào để chỉ ghi lại một dòng văn bản? Tốt hơn là mà không cần sao chép mã trong nhiều lần kiểm tra.Có cách nào đơn giản về việc sử dụng slf4j trong các bài kiểm tra đơn vị không?

Trả lời

10

Tôi cũng muốn sử dụng slf4j trong các thử nghiệm JUnit tôi cho lớp DAO tôi. Nó sẽ giúp ích khi bạn đang tạo một thử nghiệm mới hoặc sửa đổi một cái cũ. Tôi thường để lại kết quả đăng nhập cũ của mình ở mức gỡ lỗi và tạo các câu lệnh ghi nhật ký mới ở mức thông tin trong khi tôi vẫn đang tích cực làm việc trên mã trong phương thức đó. Một trong những lớp JUnit của tôi sẽ giống như thế này:

package com.example.mydao; 

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
// other imports not shown... 

public class TestMyDAO extends TestCase { 

    private static final Logger logger = 
     LoggerFactory.getLogger(TestMyDAO.class); 


    public void testA() { 
     logger.debug("Logging from testA() method"); 
    } 

    public void testB() { 
     logger.debug("Logging from testB() method"); 
    } 

    public void testThatIAmWorkingOn() { 
     logger.info("Logging from my new test method at INFO level"); 
    } 

} 

Tôi đang sử dụng log4j là nhà cung cấp khai thác gỗ thực tế, do tập tin cấu hình log4j.xml của tôi trông như thế này:

<?xml version="1.0" encoding="UTF-8"?> 
    <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> 
    <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false"> 
    <appender name="consoleAppender" class="org.apache.log4j.ConsoleAppender"> 
     <layout class="org.apache.log4j.PatternLayout"> 
      <param name="ConversionPattern" value="%d %-5p [%c{1}] %m %n" /> 
     </layout> 
    </appender> 

    <logger name="com.example.mydao" additivity="false"> 
     <level value="INFO" /> 
     <appender-ref ref="consoleAppender"/> 
    </logger> 

    <logger name="org.hibernate" additivity="false"> 
     <level value="WARN" /> 
     <appender-ref ref="consoleAppender"/> 
    </logger> 

    <logger name="org.hibernate.connection.DriverManagerConnectionProvider" additivity="false"> 
     <level value="INFO" /> 
     <appender-ref ref="consoleAppender"/> 
    </logger> 

    <logger name="org.hibernate.connection.C3P0ConnectionProvider" additivity="false"> 
     <level value="INFO" /> 
     <appender-ref ref="consoleAppender"/> 
    </logger> 

    <logger name="com.mchange" additivity="false"> 
     <level value="WARN" /> 
     <appender-ref ref="consoleAppender"/> 
    </logger> 

    <logger name="com.mchange.v2.resourcepool.BasicResourcePool" additivity="false"> 
     <level value="INFO" /> 
     <appender-ref ref="consoleAppender"/> 
    </logger> 

    <logger name="com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource" additivity="false"> 
     <level value="INFO" /> 
     <appender-ref ref="consoleAppender"/> 
    </logger> 

    <logger name="com.mchange.v2.c3p0.C3P0Registry" additivity="false"> 
     <level value="INFO" /> 
     <appender-ref ref="consoleAppender"/> 
    </logger> 

    <root> 
     <priority value ="WARN" /> 
     <appender-ref ref="consoleAppender"/> 
    </root> 

</log4j:configuration> 

này mang lại cho tôi những thông tin -level đầu ra từ lớp JUnit của tôi, cũng như một số công cụ hữu ích từ thời gian chạy Hibernate và các thư viện khác được sử dụng với Hibernate. Điều chỉnh theo sở thích của riêng bạn.

Cuối cùng, tôi cần phải chắc chắn rằng tất cả các thư viện sau nằm trong classpath của tôi khi tôi thực hiện các bài kiểm tra JUnit:

  • slf4j-api-1.6.0.jar
  • slf4j-log4j12-1.6.0.jar
  • log4j-1.2.16.jar
  • log4j.xml (cấu hình của tôi tệp, được hiển thị ở trên)
  • Một số phiên bản của JUnit runtime JAR
  • Tất cả các JAR thường có mặt khi chạy ứng dụng của bạn trong sản xuất

Đây là những gì tôi làm khi sử dụng log4j. Nếu bạn sử dụng triển khai ghi nhật ký khác, hãy điều chỉnh cho phù hợp. Nó không quan trọng nếu bạn đang sử dụng một phiên bản khác của slf4j, miễn là các "API" và các JAR thực hiện có cùng phiên bản (tôi là cả 1.6.0).

+0

Và để tránh trùng lặp mã, bạn có thể di chuyển nhập khẩu và khai báo 'Logger' thành lớp con trừu tượng' TestCase'. –

11

Tại sao bạn muốn ghi lại mọi thứ trong thử nghiệm đơn vị của mình? Các bài kiểm tra đơn vị nên được thông qua/thất bại và nên sử dụng khung kiểm tra để chỉ ra điều đó. Bạn không muốn đọc qua đầu ra để xem thử nghiệm đã trôi qua hay thất bại chưa. Và nếu nó thất bại, hãy chạy nó trong IDE/debugger của bạn là cách tốt nhất để sửa chữa nó.

+11

Bởi vì đôi khi hữu ích khi biết TẠI SAO một thử nghiệm không thành công hoặc có thể in chỉ số hiệu suất trong trường hợp bạn muốn theo dõi tình cờ. – BjornS

+6

Nếu bạn muốn thực hiện kiểm tra hiệu suất, hãy thực hiện đúng và chụp và vẽ đồ thị các số. Tình cờ đánh bóng một số con số từ chạy UT không phải là cách để đo lường hiệu suất. Và về lý do tại sao thử nghiệm không thành công, bạn nên viết xác nhận của mình để văn bản cho bạn biết điều gì đã xảy ra. Tại nơi làm việc, sản phẩm của chúng tôi có hàng chục nghìn bài kiểm tra đơn vị; bạn nghĩ chúng ta sẽ ở đâu nếu chúng ta phải đọc kết quả từ những thứ đó? – dty

+2

Tôi đã không nói thử nghiệm hiệu suất, tôi chỉ đơn giản nói để theo dõi tình cờ nó như là một ví dụ về lý do tại sao bạn có thể muốn đăng nhập vào các thử nghiệm của bạn. Đối với công việc của bạn, có chúng tôi có hàng chục ngàn bài kiểm tra là tốt và bạn sẽ ngạc nhiên như thế nào một cách nhanh chóng, bạn có thể tìm thấy những thông tin bạn muốn liên quan đến một bài kiểm tra cụ thể. Bên cạnh đó, bạn sẽ không cần phải đọc chúng, trừ khi bạn thực sự cần, và khi bạn thực sự cần, nó tiện dụng chết tiệt đã có các bản ghi ở đó. – BjornS

-1

Nó có vẻ là một mùi hôi đối với tôi.

Bạn nên luôn luôn tránh kiểm tra thủ công hoặc xác minh để kiểm tra đơn vị.

Đơn vị kiểm tra nên được tự động, can thiệp của con người chỉ nên cần thiết nếu xây dựng các công cụ của bạn nói với bạn rằng thử nghiệm nhất định thất bại, và lý do thất bại nên được cung cấp sử dụng tất cả các phương pháp xác minh (ví dụ assertEquals)

+2

Chắc chắn rồi. OP muốn biết mã * nên * trông như thế nào, và nhiều người trong chúng ta đề xuất rằng mã đó không tồn tại. Đó là cách nó * nên *. – iX3

+0

đủ thú vị, một câu trả lời khác từ dyt về cơ bản là nói điều tương tự (mọi người nên tránh đăng nhập vào các bài kiểm tra đơn vị vì blablabla). Câu trả lời của tôi là nhận được nhiều downvotes hơn. LOL –

+0

Việc ghi nhật ký trong quá trình kiểm tra thường vô cùng vô giá, đặc biệt khi các thử nghiệm thất bại. Điều này tất nhiên cần phải được cân bằng với quá nhiều đăng nhập khi các bài kiểm tra được đi qua hoặc các bản ghi trở thành không đọc được. – AntonPiatek

2

Chúng tôi sử dụng log4j như logger đầu ra của chúng tôi;

private static Logger log = LoggerFactory.getLogger(MyClassHere.class); 

slf4j nên tìm và sử dụng log4j mà không có vấn đề nếu bạn định cấu hình chính xác. Để làm cho cuộc sống dễ dàng, tôi sẽ sử dụng mô hình Eclipse này, vì bạn sẽ được viết mã này một chút công bằng:

private static Logger log = LoggerFactory.getLogger(${enclosing_type}.class); 
${:import(org.slf4j.Logger,org.slf4j.LoggerFactory)} 

cho các bài kiểm tra tôi sẽ khuyên bạn không tăng so với mực INFO và giữ hầu hết mọi thứ để DEBUG . Nếu bạn thực sự muốn bẫy rất nhiều lỗi một cách thông minh thì tôi khuyên bạn nên xem xét PositronLogger, một ứng dụng ghi nhật ký, sẽ lặng lẽ nhặt mọi thứ xuống TRACE nhưng chỉ đổ nó vào tập tin nếu nó chụp ERROR; loại giống như thời gian đi du lịch :)

http://github.com/andreaja/PositronLogger

+0

Tôi cần phải làm điều này 'getLogger()' trong mỗi bài kiểm tra đơn vị bên trong một số phương pháp '@ Before'-chú thích, phải không? – yegor256

+0

Không, chỉ là tham chiếu tĩnh riêng, sau đó bạn có thể chỉ cần gọi log.debug ("một số nội dung"); bất cứ nơi nào bạn muốn. Chỉnh sửa: Tôi nên làm rõ; LoggerFactory.getLogger() là một phần của tham chiếu tĩnh, bạn không cần phải gọi nó trong @Before của bạn, chỉ cần nhập nó như là một trường trong lớp thử nghiệm của bạn và nó sẽ hoạt động. Một ví dụ ngắn gọn: class MyTests {private static Logger log = LoggerFactory.getLogger (MyTests.class); @Test public void magic() {log.info ("..."); }} – BjornS

0

Slf4j là mặt tiền ghi nhật ký nơi bạn có thể quyết định triển khai khi chạy. Slf4j chỉ là một API. Ví dụ, bạn có thể sử dụng log4j như thực hiện cơ bản. Bạn cần bao gồm hai phụ thuộc trong tệp pom.xml của bạn cho việc này.

<!-- Depend on slf4j API --> 
    <dependency> 
     <groupId>org.slf4j</groupId> 
     <artifactId>slf4j-api</artifactId> 
     <version>1.7.12</version> 
    </dependency> 
    <!-- Use log4j as the slf4j implementation --> 
    <dependency> 
     <groupId>org.slf4j</groupId> 
     <artifactId>slf4j-log4j12</artifactId> 
     <version>1.7.12</version> 
    </dependency> 

Vấn đề là khi chạy thử nghiệm đơn vị trong IDE hoặc qua mvn test, có thể gây khó chịu khi thiết lập cấu hình log4j. Đặc biệt trong một cách mà chỉ hoạt động mà không cần phải làm bất cứ điều gì. Log4j từ chối đăng nhập bất kỳ thứ gì theo mặc định, trừ khi bạn có tệp log4j.properties trên đường dẫn lớp hoặc đặt -Dlog4j.configuration=file:///path/to/log4j.properties.

Một giải pháp là để đưa vào các bài kiểm tra đơn vị, mã để thiết lập cấu hình log4j lập trình:

@BeforeClass 
    public static void beforeClass() { 
     BasicConfigurator.resetConfiguration(); 
     BasicConfigurator.configure(); 
    } 

này chỉ hoạt động, tuy nhiên nó cần phải được đưa vào mỗi thử nghiệm đơn vị đó là một nỗi đau. .

5

Một giải pháp khác là chuyển đổi triển khai ghi nhật ký thành triển khai đơn giản chỉ để thử nghiệm.

Vì vậy, trong pom.xml của bạn

<!-- Depend on slf4j API --> 
    <dependency> 
     <groupId>org.slf4j</groupId> 
     <artifactId>slf4j-api</artifactId> 
     <version>1.7.12</version> 
    </dependency> 

    <!-- Use SimpleLogger as the slf4j implementation in test --> 
    <dependency> 
     <groupId>org.slf4j</groupId> 
     <artifactId>slf4j-simple</artifactId> 
     <version>1.7.12</version> 
     <scope>test</scope> 
    </dependency> 

    <!-- Use log4j as the slf4j implementation during runtime (not test) --> 
    <dependency> 
     <groupId>org.slf4j</groupId> 
     <artifactId>slf4j-log4j12</artifactId> 
     <version>1.7.12</version> 
     <scope>runtime</scope> 
    </dependency> 

Các SimpleLogger chỉ đăng nhập tất cả mọi thứ để stderr theo mặc định và không đòi hỏi bất kỳ tập tin cấu hình

+1

Mức nhật ký mặc định SimpleLogger là INFO. Để thay đổi nó thành DEBUG, ví dụ, sử dụng tùy chọn JVM -Dorg.slf4j.simpleLogger.defaultLogLevel = DEBUG –

0

Thêm đăng nhập trong khi viết các bài kiểm tra mới rất hữu ích. Đồng thời, khi các thử nghiệm đang được chạy trong một đường ống CI hoặc CD, bạn muốn đăng nhập bị vô hiệu hóa (hoặc ít nhất là tiết kiệm). Đôi khi những thất bại là tạm thời đặc biệt là trong một end-to-end chạy, do đó, có đầu ra có liên quan trên nhật ký giao diện điều khiển của công việc CI là hữu ích. Bài viết này mô tả nó rất tốt - https://gualtierotesta.wordpress.com/2015/11/01/tutorial-logging-during-tests/

Các vấn đề liên quan