I am getting started with software testing in Java and was wondering if test-driven dev and white-box testing could be combined directly... If not, what ways can we extend TDD to combine white box testing?
TDD and white-box testing are fundamentally incompatible with each other.
White-box testing means that you write the test based on knowledge of the internals of the code.
TDD means that you write the tests before the code.
It is fundamentally impossible to write tests based on knowledge of code that does not exist.
Note that you of course can write additional white-box tests after you have implemented the code. But that has nothing to do with TDD.
It is of course also possible to do some sort of "fake" TDD, where you write the code in your head, and then write a white-box test based on your mental image of what the code will be. But again, that is not TDD. In TDD, the tests drive the code. If you imagine the code in your head before you write the test, then you are not doing TDD. It doesn't matter that you didn't write the code down in your IDE, you still did write it in your head.
Some definitions (my emphasis):
Test-driven development (TDD) is a software development process relying on software requirements being converted to test cases before software is fully developed, […]. This is opposed to software being developed first and test cases created later.
Basically, TDD means writing the tests before changing any of the underlying code. Crucially, the TDD process includes changing the underlying code, not just writing the tests.
White-box testing […] is a method of software testing that tests internal structures or workings of an application, as opposed to its functionality (i.e. black-box testing).
In other words, white-box testing verifies the internals of an application with full visibility of the code, while black-box testing verifies the externally visible functionality, with (ideally) no knowledge of the underlying code. Contrary to TDD, white-box testing is only concerned with the test writing phase, not with changing the underlying code.
TDD therefore requires white-box testing: it is not possible to write the underlying code to satisfy the tests without having knowledge of the existing underlying code. The only exception would be when the new code simply wraps the underlying system, and so requires only knowledge of the existing inputs and outputs.
The questions, comments, and answers contain so many problems that I felt compelled to write an answer to this heavily downvoted question.
There are, at least, two different scenarios in which TDD is successfully applied.
There are, of course, infinitely many scenarios in which it was futile. But that's not a point. Not every rocket company ends up launching a rocket.
Scenario 1: (Macroscopic) Test-Driven Design (TDD Design)
In this approach, TDD is used to help the architect think through how the software's architecture and interfaces should look like, without being tied up with details such as implementation specifics.
TDD Design tests tend to be high-level, covering the API level, sometimes at the end-to-end level. TDD Design may entail creating and then throwing away a lot of tests as well as mock implementations.
To the extent that "very high level tests tend to be white box tests", TDD Design tend to be white box.
Scenario 2: (Microscopic) Incremental Test-Driven Development (ITDD)
In this approach, the software framework is already well-established, and code changes tend to be incremental, in that existing functionality are seldom affected. ITDD ensures that new code changes have high coverage to begin with, and that none of the existing functionality were adversely affected.
To the extent that "incremental tests tend to be unit tests", ITDD tend to result in additions to an existing unit test suite.